Merge pull request #3098 from aws-lumberyard-dev/Atom/guthadam/atomtools_refactor_document_system

AtomTools: Unified ME and SMC document system into AtomToolsFramework shared classes and buses
This commit is contained in:
Guthrie Adams
2021-08-17 10:11:21 -05:00
committed by GitHub
58 changed files with 1554 additions and 1777 deletions
@@ -47,28 +47,28 @@ def open_material(file_path):
"""
:return: uuid of material document opened
"""
return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "OpenDocument", file_path)
return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "OpenDocument", file_path)
def is_open(document_id):
"""
:return: bool
"""
return materialeditor.MaterialDocumentRequestBus(bus.Event, "IsOpen", document_id)
return azlmbr.atomtools.AtomToolsDocumentRequestBus(bus.Event, "IsOpen", document_id)
def save_document(document_id):
"""
:return: bool success
"""
return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "SaveDocument", document_id)
return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "SaveDocument", document_id)
def save_document_as_copy(document_id, target_path):
"""
:return: bool success
"""
return materialeditor.MaterialDocumentSystemRequestBus(
return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(
bus.Broadcast, "SaveDocumentAsCopy", document_id, target_path
)
@@ -77,7 +77,7 @@ def save_document_as_child(document_id, target_path):
"""
:return: bool success
"""
return materialeditor.MaterialDocumentSystemRequestBus(
return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(
bus.Broadcast, "SaveDocumentAsChild", document_id, target_path
)
@@ -86,39 +86,39 @@ def save_all():
"""
:return: bool success
"""
return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "SaveAllDocuments")
return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "SaveAllDocuments")
def close_document(document_id):
"""
:return: bool success
"""
return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseDocument", document_id)
return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "CloseDocument", document_id)
def close_all_documents():
"""
:return: bool success
"""
return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocuments")
return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocuments")
def close_all_except_selected(document_id):
"""
:return: bool success
"""
return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocumentsExcept", document_id)
return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocumentsExcept", document_id)
def get_property(document_id, property_name):
"""
:return: property value or invalid value if the document is not open or the property_name can't be found
"""
return materialeditor.MaterialDocumentRequestBus(bus.Event, "GetPropertyValue", document_id, property_name)
return azlmbr.atomtools.AtomToolsDocumentRequestBus(bus.Event, "GetPropertyValue", document_id, property_name)
def set_property(document_id, property_name, value):
materialeditor.MaterialDocumentRequestBus(bus.Event, "SetPropertyValue", document_id, property_name, value)
azlmbr.atomtools.AtomToolsDocumentRequestBus(bus.Event, "SetPropertyValue", document_id, property_name, value)
def is_pane_visible(pane_name):
@@ -175,7 +175,7 @@ def wait_for_condition(function, timeout_in_seconds=1.0):
with Timeout(timeout_in_seconds) as t:
while True:
try:
atomtools.general.idle_wait_frames(1)
azlmbr.atomtools.general.idle_wait_frames(1)
except Exception:
print("WARNING: Couldn't wait for frame")
@@ -269,6 +269,6 @@ class ScreenshotHelper:
def capture_screenshot(file_path):
return ScreenshotHelper(atomtools.general.idle_wait_frames).capture_screenshot_blocking(
return ScreenshotHelper(azlmbr.atomtools.general.idle_wait_frames).capture_screenshot_blocking(
os.path.join(file_path)
)
@@ -0,0 +1,71 @@
/*
* 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
#include <AzCore/RTTI/RTTI.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
namespace AtomToolsFramework
{
/**
* AtomToolsDocument provides an API for modifying and saving documents.
*/
class AtomToolsDocument
: public AtomToolsDocumentRequestBus::Handler
{
public:
AZ_RTTI(AtomToolsDocument, "{8992DF74-88EC-438C-B280-6E71D4C0880B}");
AZ_CLASS_ALLOCATOR(AtomToolsDocument, AZ::SystemAllocator, 0);
AZ_DISABLE_COPY(AtomToolsDocument);
AtomToolsDocument();
virtual ~AtomToolsDocument();
const AZ::Uuid& GetId() const;
////////////////////////////////////////////////////////////////////////
// AtomToolsDocumentRequestBus::Handler implementation
AZStd::string_view GetAbsolutePath() const override;
AZStd::string_view GetRelativePath() const override;
const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const override;
const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const override;
bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override;
void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override;
bool Open(AZStd::string_view loadPath) override;
bool Reopen() override;
bool Save() override;
bool SaveAsCopy(AZStd::string_view savePath) override;
bool SaveAsChild(AZStd::string_view savePath) override;
bool Close() override;
bool IsOpen() const override;
bool IsModified() const override;
bool IsSavable() const override;
bool CanUndo() const override;
bool CanRedo() const override;
bool Undo() override;
bool Redo() override;
bool BeginEdit() override;
bool EndEdit() override;
////////////////////////////////////////////////////////////////////////
protected:
// Unique id of this document
AZ::Uuid m_id = AZ::Uuid::CreateRandom();
// Relative path to the material source file
AZStd::string m_relativePath;
// Absolute path to the material source file
AZStd::string m_absolutePath;
AZStd::any m_invalidValue;
AtomToolsFramework::DynamicProperty m_invalidProperty;
};
} // namespace AtomToolsFramework
@@ -7,80 +7,77 @@
*/
#pragma once
#include <Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h>
#include <Atom/RPI.Public/Material/Material.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/std/any.h>
#include <AtomToolsFramework/DynamicProperty/DynamicProperty.h>
#include <AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h>
namespace MaterialEditor
namespace AtomToolsFramework
{
class MaterialDocumentNotifications
class AtomToolsDocumentNotifications
: public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
//! Signal that a material document was created
//! @param documentId unique id of material document for which the notification is sent
//! Signal that a document was created
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentCreated([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a material document was destroyed
//! @param documentId unique id of material document for which the notification is sent
//! Signal that a document was destroyed
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentDestroyed([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a material document was opened
//! @param documentId unique id of material document for which the notification is sent
//! Signal that a document was opened
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentOpened([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a material document was closed
//! @param documentId unique id of material document for which the notification is sent
//! Signal that a document was closed
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentClosed([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a material document was saved
//! @param documentId unique id of material document for which the notification is sent
//! Signal that a document was saved
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentSaved([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a material document was selected
//! @param documentId unique id of material document for which the notification is sent
//! Signal that a document was selected
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentSelected([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a material document was modified
//! @param documentId unique id of material document for which the notification is sent
//! Signal that a document was modified
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentModified([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a material document dependency was modified
//! @param documentId unique id of material document for which the notification is sent
//! Signal that a document dependency was modified
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentDependencyModified([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a material document was modified externally
//! @param documentId unique id of material document for which the notification is sent
//! Signal that a document was modified externally
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentExternallyModified([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a material document undo state was updated
//! @param documentId unique id of material document for which the notification is sent
//! Signal that a document undo state was updated
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentUndoStateChanged([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a material property changed
//! @param documentId unique id of material document for which the notification is sent
//! Signal that a property changed
//! @param documentId unique id of document for which the notification is sent
//! @param property object containing the property value and configuration that was modified
virtual void OnDocumentPropertyValueModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {}
//! Signal that the property configuration has been changed.
//! @param documentId unique id of material document for which the notification is sent
//! @param documentId unique id of document for which the notification is sent
//! @param property object containing the property value and configuration that was modified
virtual void OnDocumentPropertyConfigModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {}
//! Signal that the property group visibility has been changed.
//! @param documentId unique id of material document for which the notification is sent
//! @param documentId unique id of document for which the notification is sent
//! @param groupId id of the group that changed
//! @param visible whether the property group is visible
virtual void OnDocumentPropertyGroupVisibilityChanged([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AZ::Name& groupId, [[maybe_unused]] bool visible) {}
};
using MaterialDocumentNotificationBus = AZ::EBus<MaterialDocumentNotifications>;
} // namespace MaterialEditor
using AtomToolsDocumentNotificationBus = AZ::EBus<AtomToolsDocumentNotifications>;
} // namespace AtomToolsFramework
@@ -0,0 +1,95 @@
/*
* 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
#include <AzCore/std/any.h>
#include <AtomToolsFramework/DynamicProperty/DynamicProperty.h>
#include <AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h>
namespace AtomToolsFramework
{
class AtomToolsDocumentRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
typedef AZ::Uuid BusIdType;
//! Get absolute path of document
virtual AZStd::string_view GetAbsolutePath() const = 0;
//! Get relative path of document
virtual AZStd::string_view GetRelativePath() const = 0;
//! Return property value
//! If the document is not open or the id can't be found, an invalid value is returned instead.
virtual const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const = 0;
//! Returns a property object
//! If the document is not open or the id can't be found, an invalid property is returned.
virtual const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const = 0;
//! Returns whether a property group is visible
//! If the document is not open or the id can't be found, returns false.
virtual bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const = 0;
//! Modify document property value
virtual void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) = 0;
//! Load document and related data
//! @param loadPath absolute path of document to load
virtual bool Open(AZStd::string_view loadPath) = 0;
//! Reopen document preserving edits
virtual bool Reopen() = 0;
//! Save document to file
virtual bool Save() = 0;
//! Save document copy
//! @param savePath absolute path where document is saved
virtual bool SaveAsCopy(AZStd::string_view savePath) = 0;
//! Save document to a new source file derived from of the open document
//! @param savePath absolute path where document is saved
virtual bool SaveAsChild(AZStd::string_view savePath) = 0;
//! Close document and reset its data
virtual bool Close() = 0;
//! Document is loaded
virtual bool IsOpen() const = 0;
//! Document has changes pending
virtual bool IsModified() const = 0;
//! Can the document be saved
virtual bool IsSavable() const = 0;
//! Returns true if there are reversible modifications to the document
virtual bool CanUndo() const = 0;
//! Returns true if there are changes that were reversed and can be re-applied to the document
virtual bool CanRedo() const = 0;
//! Restores the previous state of the document
virtual bool Undo() = 0;
//! Restores the next state of the document
virtual bool Redo() = 0;
//! Signal that editing is about to begin, like beginning to drag a slider control
virtual bool BeginEdit() = 0;
//! Signal that editing has completed, like after releasing the mouse button after continuously dragging a slider control
virtual bool EndEdit() = 0;
};
using AtomToolsDocumentRequestBus = AZ::EBus<AtomToolsDocumentRequests>;
} // namespace AtomToolsFramework
@@ -0,0 +1,78 @@
/*
* 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
#include <AzCore/EBus/EBus.h>
namespace AtomToolsFramework
{
class AtomToolsDocument;
//! AtomToolsDocumentSystemRequestBus provides high level requests for menus, scripts, etc.
class AtomToolsDocumentSystemRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//! Register a document factory function used to create specific document types
virtual void RegisterDocumentType(AZStd::function<AtomToolsDocument*()> documentCreator) = 0;
//! Create a document object
//! @return Uuid of new document, or null Uuid if failed
virtual AZ::Uuid CreateDocument() = 0;
//! Destroy a document object with the specified id
//! @return true if Uuid was found and removed, otherwise false
virtual bool DestroyDocument(const AZ::Uuid& documentId) = 0;
//! Open a document for editing
//! @param sourcePath document to open.
//! @return unique id of new document if successful, otherwise null Uuid
virtual AZ::Uuid OpenDocument(AZStd::string_view sourcePath) = 0;
//! Create a new document by specifying a source and prompting the user for destination path.
//! @param sourcePath document to open.
//! @param targetPath location where document is saved.
//! @return unique id of new document if successful, otherwise null Uuid
virtual AZ::Uuid CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) = 0;
//! Close the specified document
//! @param documentId unique id of document to close
virtual bool CloseDocument(const AZ::Uuid& documentId) = 0;
//! Close all documents
virtual bool CloseAllDocuments() = 0;
//! Close all documents except for documentId
//! @param documentId unique id of document to not close
virtual bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) = 0;
//! Save the specified document
//! @param documentId unique id of document to save
virtual bool SaveDocument(const AZ::Uuid& documentId) = 0;
//! Save the specified document to a different file
//! @param documentId unique id of document to save
//! @param targetPath location where document is saved.
virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0;
//! Save the specified document to a different file, referencing the original document as its parent
//! @param documentId unique id of document to save
//! @param targetPath location where document is saved.
virtual bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0;
//! Save all documents
virtual bool SaveAllDocuments() = 0;
};
using AtomToolsDocumentSystemRequestBus = AZ::EBus<AtomToolsDocumentSystemRequests>;
} // namespace AtomToolsFramework
@@ -0,0 +1,30 @@
/*
* 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 <AzCore/Memory/Memory.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/UserSettings/UserSettings.h>
#endif
namespace AtomToolsFramework
{
struct AtomToolsDocumentSystemSettings
: public AZ::UserSettings
{
AZ_RTTI(AtomToolsDocumentSystemSettings, "{9E576D4F-A74A-4326-9135-C07284D0A3B9}", AZ::UserSettings);
AZ_CLASS_ALLOCATOR(AtomToolsDocumentSystemSettings, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* context);
bool m_showReloadDocumentPrompt = true;
};
} // namespace AtomToolsFramework
@@ -8,6 +8,7 @@
#include <AtomToolsFrameworkModule.h>
#include <AtomToolsFrameworkSystemComponent.h>
#include <Document/AtomToolsDocumentSystemComponent.h>
#include <Window/AtomToolsMainWindowSystemComponent.h>
namespace AtomToolsFramework
@@ -16,6 +17,7 @@ namespace AtomToolsFramework
{
m_descriptors.insert(m_descriptors.end(), {
AtomToolsFrameworkSystemComponent::CreateDescriptor(),
AtomToolsDocumentSystemComponent::CreateDescriptor(),
AtomToolsMainWindowSystemComponent::CreateDescriptor(),
});
}
@@ -24,6 +26,7 @@ namespace AtomToolsFramework
{
return AZ::ComponentTypeList{
azrtti_typeid<AtomToolsFrameworkSystemComponent>(),
azrtti_typeid<AtomToolsDocumentSystemComponent>(),
azrtti_typeid<AtomToolsMainWindowSystemComponent>(),
};
}
@@ -0,0 +1,149 @@
/*
* 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 <AtomToolsFramework/Document/AtomToolsDocument.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
namespace AtomToolsFramework
{
AtomToolsDocument::AtomToolsDocument()
{
AtomToolsDocumentRequestBus::Handler::BusConnect(m_id);
AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id);
}
AtomToolsDocument::~AtomToolsDocument()
{
AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id);
AtomToolsDocumentRequestBus::Handler::BusDisconnect();
}
const AZ::Uuid& AtomToolsDocument::GetId() const
{
return m_id;
}
AZStd::string_view AtomToolsDocument::GetAbsolutePath() const
{
return m_absolutePath;
}
AZStd::string_view AtomToolsDocument::GetRelativePath() const
{
return m_relativePath;
}
const AZStd::any& AtomToolsDocument::GetPropertyValue(const AZ::Name& propertyFullName) const
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return m_invalidValue;
}
const AtomToolsFramework::DynamicProperty& AtomToolsDocument::GetProperty(const AZ::Name& propertyFullName) const
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return m_invalidProperty;
}
bool AtomToolsDocument::IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
void AtomToolsDocument::SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value)
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
}
bool AtomToolsDocument::Open(AZStd::string_view loadPath)
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
bool AtomToolsDocument::Reopen()
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
bool AtomToolsDocument::Save()
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
bool AtomToolsDocument::SaveAsCopy(AZStd::string_view savePath)
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
bool AtomToolsDocument::SaveAsChild(AZStd::string_view savePath)
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
bool AtomToolsDocument::Close()
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
bool AtomToolsDocument::IsOpen() const
{
return false;
}
bool AtomToolsDocument::IsModified() const
{
return false;
}
bool AtomToolsDocument::IsSavable() const
{
return false;
}
bool AtomToolsDocument::CanUndo() const
{
return false;
}
bool AtomToolsDocument::CanRedo() const
{
return false;
}
bool AtomToolsDocument::Undo()
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
bool AtomToolsDocument::Redo()
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
bool AtomToolsDocument::BeginEdit()
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
bool AtomToolsDocument::EndEdit()
{
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
} // namespace AtomToolsFramework
@@ -0,0 +1,511 @@
/*
* 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 <AtomToolsFramework/Debug/TraceRecorder.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/Asset/AssetSystemBus.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <Document/AtomToolsDocumentSystemComponent.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QApplication>
#include <QMessageBox>
#include <QString>
AZ_POP_DISABLE_WARNING
namespace AtomToolsFramework
{
AtomToolsDocumentSystemComponent::AtomToolsDocumentSystemComponent()
{
}
void AtomToolsDocumentSystemComponent::Reflect(AZ::ReflectContext* context)
{
AtomToolsDocumentSystemSettings::Reflect(context);
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
serialize->Class<AtomToolsDocumentSystemComponent, AZ::Component>()
->Version(0);
if (AZ::EditContext* ec = serialize->GetEditContext())
{
ec->Class<AtomToolsDocumentSystemComponent>("AtomToolsDocumentSystemComponent", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System"))
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
;
}
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<AtomToolsDocumentSystemRequestBus>("AtomToolsDocumentSystemRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "atomtools")
->Event("CreateDocument", &AtomToolsDocumentSystemRequestBus::Events::CreateDocument)
->Event("DestroyDocument", &AtomToolsDocumentSystemRequestBus::Events::DestroyDocument)
->Event("OpenDocument", &AtomToolsDocumentSystemRequestBus::Events::OpenDocument)
->Event("CreateDocumentFromFile", &AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile)
->Event("CloseDocument", &AtomToolsDocumentSystemRequestBus::Events::CloseDocument)
->Event("CloseAllDocuments", &AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments)
->Event("CloseAllDocumentsExcept", &AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept)
->Event("SaveDocument", &AtomToolsDocumentSystemRequestBus::Events::SaveDocument)
->Event("SaveDocumentAsCopy", &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy)
->Event("SaveDocumentAsChild", &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsChild)
->Event("SaveAllDocuments", &AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments)
;
behaviorContext->EBus<AtomToolsDocumentRequestBus>("AtomToolsDocumentRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "atomtools")
->Event("GetAbsolutePath", &AtomToolsDocumentRequestBus::Events::GetAbsolutePath)
->Event("GetRelativePath", &AtomToolsDocumentRequestBus::Events::GetRelativePath)
->Event("GetPropertyValue", &AtomToolsDocumentRequestBus::Events::GetPropertyValue)
->Event("SetPropertyValue", &AtomToolsDocumentRequestBus::Events::SetPropertyValue)
->Event("Open", &AtomToolsDocumentRequestBus::Events::Open)
->Event("Reopen", &AtomToolsDocumentRequestBus::Events::Reopen)
->Event("Close", &AtomToolsDocumentRequestBus::Events::Close)
->Event("Save", &AtomToolsDocumentRequestBus::Events::Save)
->Event("SaveAsChild", &AtomToolsDocumentRequestBus::Events::SaveAsChild)
->Event("SaveAsCopy", &AtomToolsDocumentRequestBus::Events::SaveAsCopy)
->Event("IsOpen", &AtomToolsDocumentRequestBus::Events::IsOpen)
->Event("IsModified", &AtomToolsDocumentRequestBus::Events::IsModified)
->Event("IsSavable", &AtomToolsDocumentRequestBus::Events::IsSavable)
->Event("CanUndo", &AtomToolsDocumentRequestBus::Events::CanUndo)
->Event("CanRedo", &AtomToolsDocumentRequestBus::Events::CanRedo)
->Event("Undo", &AtomToolsDocumentRequestBus::Events::Undo)
->Event("Redo", &AtomToolsDocumentRequestBus::Events::Redo)
->Event("BeginEdit", &AtomToolsDocumentRequestBus::Events::BeginEdit)
->Event("EndEdit", &AtomToolsDocumentRequestBus::Events::EndEdit)
;
}
}
void AtomToolsDocumentSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService"));
}
void AtomToolsDocumentSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService"));
}
void AtomToolsDocumentSystemComponent::Init()
{
}
void AtomToolsDocumentSystemComponent::Activate()
{
m_documentMap.clear();
m_settings = AZ::UserSettings::CreateFind<AtomToolsDocumentSystemSettings>(AZ_CRC_CE("AtomToolsDocumentSystemSettings"), AZ::UserSettings::CT_GLOBAL);
AtomToolsDocumentSystemRequestBus::Handler::BusConnect();
AtomToolsDocumentNotificationBus::Handler::BusConnect();
}
void AtomToolsDocumentSystemComponent::Deactivate()
{
AZ::TickBus::Handler::BusDisconnect();
AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
AtomToolsDocumentSystemRequestBus::Handler::BusDisconnect();
m_documentMap.clear();
}
void AtomToolsDocumentSystemComponent::RegisterDocumentType(AZStd::function<AtomToolsDocument*()> documentCreator)
{
m_documentCreator = documentCreator;
}
AZ::Uuid AtomToolsDocumentSystemComponent::CreateDocument()
{
if (!m_documentCreator)
{
AZ_Error("AtomToolsDocument", false, "Failed to create new document");
return AZ::Uuid::CreateNull();
}
AZStd::unique_ptr<AtomToolsDocument> document(m_documentCreator());
if (!document)
{
AZ_Error("AtomToolsDocument", false, "Failed to create new document");
return AZ::Uuid::CreateNull();
}
AZ::Uuid documentId = document->GetId();
m_documentMap.emplace(documentId, document.release());
return documentId;
}
bool AtomToolsDocumentSystemComponent::DestroyDocument(const AZ::Uuid& documentId)
{
return m_documentMap.erase(documentId) != 0;
}
void AtomToolsDocumentSystemComponent::OnDocumentExternallyModified(const AZ::Uuid& documentId)
{
m_documentIdsToReopen.insert(documentId);
if (!AZ::TickBus::Handler::BusIsConnected())
{
AZ::TickBus::Handler::BusConnect();
}
}
void AtomToolsDocumentSystemComponent::OnDocumentDependencyModified(const AZ::Uuid& documentId)
{
m_documentIdsToReopen.insert(documentId);
if (!AZ::TickBus::Handler::BusIsConnected())
{
AZ::TickBus::Handler::BusConnect();
}
}
void AtomToolsDocumentSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
{
for (const AZ::Uuid& documentId : m_documentIdsToReopen)
{
AZStd::string documentPath;
AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (m_settings->m_showReloadDocumentPrompt &&
(QMessageBox::question(QApplication::activeWindow(),
QString("Document was externally modified"),
QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()),
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes))
{
continue;
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool openResult = false;
AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Open, documentPath);
if (!openResult)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be opened"),
QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
}
}
for (const AZ::Uuid& documentId : m_documentIdsToReopen)
{
AZStd::string documentPath;
AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (m_settings->m_showReloadDocumentPrompt &&
(QMessageBox::question(QApplication::activeWindow(),
QString("Document dependencies have changed"),
QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()),
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes))
{
continue;
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool openResult = false;
AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Reopen);
if (!openResult)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be opened"),
QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
}
}
m_documentIdsToReopen.clear();
m_documentIdsToReopen.clear();
AZ::TickBus::Handler::BusDisconnect();
}
AZ::Uuid AtomToolsDocumentSystemComponent::OpenDocument(AZStd::string_view sourcePath)
{
return OpenDocumentImpl(sourcePath, true);
}
AZ::Uuid AtomToolsDocumentSystemComponent::CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath)
{
const AZ::Uuid documentId = OpenDocumentImpl(sourcePath, false);
if (documentId.IsNull())
{
return AZ::Uuid::CreateNull();
}
if (!SaveDocumentAsChild(documentId, targetPath))
{
CloseDocument(documentId);
return AZ::Uuid::CreateNull();
}
// Send document open notification after creating new one
AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
return documentId;
}
bool AtomToolsDocumentSystemComponent::CloseDocument(const AZ::Uuid& documentId)
{
bool isOpen = false;
AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsDocumentRequestBus::Events::IsOpen);
if (!isOpen)
{
// immediately destroy unopened documents
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId);
return true;
}
AZStd::string documentPath;
AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
bool isModified = false;
AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsDocumentRequestBus::Events::IsModified);
if (isModified)
{
auto selection = QMessageBox::question(QApplication::activeWindow(),
QString("Document has unsaved changes"),
QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
if (selection == QMessageBox::Cancel)
{
AZ_TracePrintf("AtomToolsDocument", "Close document canceled: %s", documentPath.c_str());
return false;
}
if (selection == QMessageBox::Yes)
{
if (!SaveDocument(documentId))
{
AZ_Error("AtomToolsDocument", false, "Close document failed because document was not saved: %s", documentPath.c_str());
return false;
}
}
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool closeResult = true;
AtomToolsDocumentRequestBus::EventResult(closeResult, documentId, &AtomToolsDocumentRequestBus::Events::Close);
if (!closeResult)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be closed"),
QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return false;
}
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId);
return true;
}
bool AtomToolsDocumentSystemComponent::CloseAllDocuments()
{
bool result = true;
auto documentMap = m_documentMap;
for (const auto& documentPair : documentMap)
{
if (!CloseDocument(documentPair.first))
{
result = false;
}
}
return result;
}
bool AtomToolsDocumentSystemComponent::CloseAllDocumentsExcept(const AZ::Uuid& documentId)
{
bool result = true;
auto documentMap = m_documentMap;
for (const auto& documentPair : documentMap)
{
if (documentPair.first != documentId)
{
if (!CloseDocument(documentPair.first))
{
result = false;
}
}
}
return result;
}
bool AtomToolsDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId)
{
AZStd::string saveDocumentPath;
AtomToolsDocumentRequestBus::EventResult(saveDocumentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath))
{
return false;
}
const QFileInfo saveInfo(saveDocumentPath.c_str());
if (saveInfo.exists() && !saveInfo.isWritable())
{
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str()));
return false;
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool result = false;
AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::Save);
if (!result)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be saved"),
QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return false;
}
return true;
}
bool AtomToolsDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath)
{
AZStd::string saveDocumentPath = targetPath;
if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath))
{
return false;
}
const QFileInfo saveInfo(saveDocumentPath.c_str());
if (saveInfo.exists() && !saveInfo.isWritable())
{
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str()));
return false;
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool result = false;
AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath);
if (!result)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be saved"),
QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return false;
}
return true;
}
bool AtomToolsDocumentSystemComponent::SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath)
{
AZStd::string saveDocumentPath = targetPath;
if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath))
{
return false;
}
const QFileInfo saveInfo(saveDocumentPath.c_str());
if (saveInfo.exists() && !saveInfo.isWritable())
{
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str()));
return false;
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool result = false;
AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::SaveAsChild, saveDocumentPath);
if (!result)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be saved"),
QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return false;
}
return true;
}
bool AtomToolsDocumentSystemComponent::SaveAllDocuments()
{
bool result = true;
for (const auto& documentPair : m_documentMap)
{
if (!SaveDocument(documentPair.first))
{
result = false;
}
}
return result;
}
AZ::Uuid AtomToolsDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen)
{
AZStd::string requestedPath = sourcePath;
if (requestedPath.empty())
{
return AZ::Uuid::CreateNull();
}
if (!AzFramework::StringFunc::Path::Normalize(requestedPath))
{
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document path is invalid:\n%1").arg(requestedPath.c_str()));
return AZ::Uuid::CreateNull();
}
// Determine if the file is already open and select it
if (checkIfAlreadyOpen)
{
for (const auto& documentPair : m_documentMap)
{
AZStd::string openDocumentPath;
AtomToolsDocumentRequestBus::EventResult(openDocumentPath, documentPair.first, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (openDocumentPath == requestedPath)
{
AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first);
return documentPair.first;
}
}
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
AZ::Uuid documentId = AZ::Uuid::CreateNull();
AtomToolsDocumentSystemRequestBus::BroadcastResult(documentId, &AtomToolsDocumentSystemRequestBus::Events::CreateDocument);
if (documentId.IsNull())
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be created"),
QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return AZ::Uuid::CreateNull();
}
traceRecorder.GetDump().clear();
bool openResult = false;
AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Open, requestedPath);
if (!openResult)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be opened"),
QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str()));
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId);
return AZ::Uuid::CreateNull();
}
return documentId;
}
}
@@ -0,0 +1,92 @@
/*
* 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
#include <AzCore/Component/Component.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AtomToolsFramework/Document/AtomToolsDocument.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QFileInfo>
#include <QString>
AZ_POP_DISABLE_WARNING
namespace AtomToolsFramework
{
//! AtomToolsDocumentSystemComponent is the central component of the Material Editor Core gem
class AtomToolsDocumentSystemComponent
: public AZ::Component
, private AZ::TickBus::Handler
, private AtomToolsDocumentNotificationBus::Handler
, private AtomToolsDocumentSystemRequestBus::Handler
{
public:
AZ_COMPONENT(AtomToolsDocumentSystemComponent, "{343A3383-6A59-4343-851B-BF84FC6CB18E}");
AtomToolsDocumentSystemComponent();
~AtomToolsDocumentSystemComponent() = default;
AtomToolsDocumentSystemComponent(const AtomToolsDocumentSystemComponent&) = delete;
AtomToolsDocumentSystemComponent& operator=(const AtomToolsDocumentSystemComponent&) = delete;
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
private:
////////////////////////////////////////////////////////////////////////
// AZ::Component interface implementation
void Init() override;
void Activate() override;
void Deactivate() override;
////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// AtomToolsDocumentNotificationBus::Handler overrides...
void OnDocumentDependencyModified(const AZ::Uuid& documentId) override;
void OnDocumentExternallyModified(const AZ::Uuid& documentId) override;
//////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// AZ::TickBus::Handler overrides...
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// AtomToolsDocumentSystemRequestBus::Handler overrides...
void RegisterDocumentType(AZStd::function<AtomToolsDocument*()> documentCreator) override;
AZ::Uuid CreateDocument() override;
bool DestroyDocument(const AZ::Uuid& documentId) override;
AZ::Uuid OpenDocument(AZStd::string_view sourcePath) override;
AZ::Uuid CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) override;
bool CloseDocument(const AZ::Uuid& documentId) override;
bool CloseAllDocuments() override;
bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) override;
bool SaveDocument(const AZ::Uuid& documentId) override;
bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) override;
bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) override;
bool SaveAllDocuments() override;
////////////////////////////////////////////////////////////////////////
AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen);
AZStd::intrusive_ptr<AtomToolsDocumentSystemSettings> m_settings;
AZStd::function<AtomToolsDocument*()> m_documentCreator;
AZStd::unordered_map<AZ::Uuid, AZStd::shared_ptr<AtomToolsDocument>> m_documentMap;
AZStd::unordered_set<AZ::Uuid> m_documentIdsToRebuild;
AZStd::unordered_set<AZ::Uuid> m_documentIdsToReopen;
const size_t m_maxMessageBoxLineCount = 15;
};
} // namespace AtomToolsFramework
@@ -0,0 +1,47 @@
/*
* 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 <AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
namespace AtomToolsFramework
{
void AtomToolsDocumentSystemSettings::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<AtomToolsDocumentSystemSettings, AZ::UserSettings>()
->Version(1)
->Field("showReloadDocumentPrompt", &AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<AtomToolsDocumentSystemSettings>(
"AtomToolsDocumentSystemSettings", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt, "Show Reload Document Prompt", "")
;
}
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<AtomToolsDocumentSystemSettings>("AtomToolsDocumentSystemSettings")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "atomtools")
->Constructor()
->Constructor<const AtomToolsDocumentSystemSettings&>()
->Property("showReloadDocumentPrompt", BehaviorValueProperty(&AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt))
;
}
}
} // namespace AtomToolsFramework
@@ -11,6 +11,11 @@ set(FILES
Include/AtomToolsFramework/Communication/LocalServer.h
Include/AtomToolsFramework/Communication/LocalSocket.h
Include/AtomToolsFramework/Debug/TraceRecorder.h
Include/AtomToolsFramework/Document/AtomToolsDocument.h
Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h
Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h
Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h
Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h
Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h
Include/AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h
Include/AtomToolsFramework/Inspector/InspectorWidget.h
@@ -32,6 +37,10 @@ set(FILES
Source/Communication/LocalServer.cpp
Source/Communication/LocalSocket.cpp
Source/Debug/TraceRecorder.cpp
Source/Document/AtomToolsDocument.cpp
Source/Document/AtomToolsDocumentSystemSettings.cpp
Source/Document/AtomToolsDocumentSystemComponent.cpp
Source/Document/AtomToolsDocumentSystemComponent.h
Source/DynamicProperty/DynamicProperty.cpp
Source/DynamicProperty/DynamicPropertyGroup.cpp
Source/Inspector/InspectorWidget.cpp
@@ -1,36 +0,0 @@
/*
* 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
#include <AzCore/EBus/EBus.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AtomCore/Instance/InstanceId.h>
namespace MaterialEditor
{
//! MaterialDocumentFactoryRequestBus provides a factory interface for creating and destroying material documents (in memory)
class MaterialDocumentFactoryRequests
: public AZ::EBusTraits
{
public:
// Only a single handler is allowed
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
//! Create a material document object
//! @return Uuid of new material document, or null Uuid if failed
virtual AZ::Uuid CreateDocument() = 0;
//! Destroy a material document object with the specified id
//! @return true if Uuid was found and removed, otherwise false
virtual bool DestroyDocument(const AZ::Uuid& documentId) = 0;
};
using MaterialDocumentFactoryRequestBus = AZ::EBus<MaterialDocumentFactoryRequests>;
} // namespace MaterialEditor
@@ -7,15 +7,10 @@
*/
#pragma once
#include <Atom/RPI.Public/Material/Material.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h>
#include <Atom/RPI.Public/Material/Material.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/std/any.h>
#include <AtomToolsFramework/DynamicProperty/DynamicProperty.h>
#include <AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h>
namespace AZ
{
@@ -39,12 +34,6 @@ namespace MaterialEditor
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
typedef AZ::Uuid BusIdType;
//! Get absolute path of material source file
virtual AZStd::string_view GetAbsolutePath() const = 0;
//! Get relative path of material source file
virtual AZStd::string_view GetRelativePath() const = 0;
//! Get material asset created by MaterialDocument
virtual AZ::Data::Asset<AZ::RPI::MaterialAsset> GetAsset() const = 0;
@@ -56,69 +45,6 @@ namespace MaterialEditor
//! Get the internal material type source data
virtual const AZ::RPI::MaterialTypeSourceData* GetMaterialTypeSourceData() const = 0;
//! Return property value
//! If the document is not open or the id can't be found, an invalid value is returned instead.
virtual const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const = 0;
//! Returns a property object
//! If the document is not open or the id can't be found, an invalid property is returned.
virtual const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const = 0;
//! Returns whether a property group is visible
//! If the document is not open or the id can't be found, returns false.
virtual bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const = 0;
//! Modify material property value
virtual void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) = 0;
//! Load source material and related data
//! @param loadPath Absolute path of material to load
virtual bool Open(AZStd::string_view loadPath) = 0;
//! Reload document preserving edits
virtual bool Rebuild() = 0;
//! Save material to source file
virtual bool Save() = 0;
//! Save material to a new source file
//! @param savePath Absolute path where material is saved
virtual bool SaveAsCopy(AZStd::string_view savePath) = 0;
//! Save material to a new source file as a child of the open material
//! @param savePath Absolute path where material is saved
virtual bool SaveAsChild(AZStd::string_view savePath) = 0;
//! Close material document and reset its data
virtual bool Close() = 0;
//! Material is loaded
virtual bool IsOpen() const = 0;
//! Material has changes pending
virtual bool IsModified() const = 0;
//! Can the document be saved
virtual bool IsSavable() const = 0;
//! Returns true if there are reversible modifications to the material document
virtual bool CanUndo() const = 0;
//! Returns true if there are changes that were reversed and can be re-applied to the material document
virtual bool CanRedo() const = 0;
//! Restores the previous state of the material document
virtual bool Undo() = 0;
//! Restores the next state of the material document
virtual bool Redo() = 0;
//! Signal that property editing is about to begin, like beginning to drag a slider control
virtual bool BeginEdit() = 0;
//! Signal that property editing has completed, like after releasing the mouse button after continuously dragging a slider control
virtual bool EndEdit() = 0;
};
using MaterialDocumentRequestBus = AZ::EBus<MaterialDocumentRequests>;
@@ -20,12 +20,11 @@ namespace MaterialEditor
struct MaterialDocumentSettings
: public AZ::UserSettings
{
AZ_RTTI(MaterialDocumentSettings, "{FA4F4BF3-BF39-4753-AAF7-AF383B868881}", AZ::UserSettings);
AZ_RTTI(MaterialDocumentSettings, "{12E8461F-65AD-4AD2-8A1D-82C3B1183522}", AZ::UserSettings);
AZ_CLASS_ALLOCATOR(MaterialDocumentSettings, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* context);
bool m_showReloadDocumentPrompt = true;
AZStd::string m_defaultMaterialTypeName = "StandardPBR";
};
} // namespace MaterialEditor
@@ -1,78 +0,0 @@
/*
* 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
#include <AzCore/EBus/EBus.h>
namespace MaterialEditor
{
static const char* MaterialExtension = "material";
static const char* MaterialTypeExtension = "materialtype";
//! MaterialDocumentSystemRequestBus provides high level file requests for menus, scripts, etc.
class MaterialDocumentSystemRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//! Create a material document object
//! @return Uuid of new material document, or null Uuid if failed
virtual AZ::Uuid CreateDocument() = 0;
//! Destroy a material document object with the specified id
//! @return true if Uuid was found and removed, otherwise false
virtual bool DestroyDocument(const AZ::Uuid& documentId) = 0;
//! Open a material document for editing
//! @param sourcePath material document to open.
//! @return unique id of new material document if successful, otherwise null Uuid
virtual AZ::Uuid OpenDocument(AZStd::string_view sourcePath) = 0;
//! Create a new document by specifying a source and prompting the user for destination path.
//! If the source file is a material type then this results in creating a new material based on that type.
//! If the source file is a material this results in creating a child material with the source file as its parent.
//! @param sourcePath material document to open.
//! @param targetPath location where document is saved.
//! @return unique id of new material document if successful, otherwise null Uuid
virtual AZ::Uuid CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) = 0;
//! Close the specified material document
//! @param documentId unique id of material document to close
virtual bool CloseDocument(const AZ::Uuid& documentId) = 0;
//! Close all material documents
virtual bool CloseAllDocuments() = 0;
//! Close all material documents except for documentId
//! @param documentId unique id of material document to not close
virtual bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) = 0;
//! Save the specified material document
//! @param documentId unique id of material document to save
virtual bool SaveDocument(const AZ::Uuid& documentId) = 0;
//! Save the specified material document to a different file
//! @param documentId unique id of material document to save
//! @param targetPath location where document is saved.
virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0;
//! Save the specified material document to a different file, referencing the original material as its parent
//! @param documentId unique id of material document to save
//! @param targetPath location where document is saved.
virtual bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0;
//! Save all material documents
virtual bool SaveAllDocuments() = 0;
};
using MaterialDocumentSystemRequestBus = AZ::EBus<MaterialDocumentSystemRequests>;
} // namespace MaterialEditor
@@ -6,53 +6,39 @@
*
*/
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
#include <Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h>
#include <Atom/RPI.Reflect/Material/MaterialFunctor.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Common/JsonUtils.h>
#include <Atom/RPI.Edit/Material/MaterialFunctorSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialPropertyId.h>
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
#include <Atom/RPI.Edit/Material/MaterialFunctorSourceData.h>
#include <Atom/RPI.Public/Material/Material.h>
#include <Atom/RPI.Reflect/Image/Image.h>
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
#include <Atom/RPI.Reflect/Material/MaterialFunctor.h>
#include <Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h>
#include <AtomCore/Instance/Instance.h>
#include <Document/MaterialDocument.h>
#include <Atom/Document/MaterialDocumentNotificationBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AtomToolsFramework/Util/MaterialPropertyUtil.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
#include <Document/MaterialDocument.h>
namespace MaterialEditor
{
MaterialDocument::MaterialDocument()
: AtomToolsFramework::AtomToolsDocument()
{
MaterialDocumentRequestBus::Handler::BusConnect(m_id);
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentCreated, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id);
}
MaterialDocument::~MaterialDocument()
{
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentDestroyed, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id);
MaterialDocumentRequestBus::Handler::BusDisconnect();
Clear();
}
const AZ::Uuid& MaterialDocument::GetId() const
{
return m_id;
}
AZStd::string_view MaterialDocument::GetAbsolutePath() const
{
return m_absolutePath;
}
AZStd::string_view MaterialDocument::GetRelativePath() const
{
return m_relativePath;
}
AZ::Data::Asset<AZ::RPI::MaterialAsset> MaterialDocument::GetAsset() const
{
return m_materialAsset;
@@ -170,17 +156,17 @@ namespace MaterialEditor
EditorMaterialFunctorResult result = RunEditorMaterialFunctors(dirtyFlags);
for (const Name& changedPropertyGroupName : result.m_updatedPropertyGroups)
{
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentPropertyGroupVisibilityChanged, m_id, changedPropertyGroupName, IsPropertyGroupVisible(changedPropertyGroupName));
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyGroupVisibilityChanged, m_id, changedPropertyGroupName, IsPropertyGroupVisible(changedPropertyGroupName));
}
for (const Name& changedPropertyName : result.m_updatedProperties)
{
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentPropertyConfigModified, m_id, GetProperty(changedPropertyName));
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyConfigModified, m_id, GetProperty(changedPropertyName));
}
}
}
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentPropertyValueModified, m_id, property);
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentModified, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyValueModified, m_id, property);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id);
}
bool MaterialDocument::Open(AZStd::string_view loadPath)
@@ -192,11 +178,11 @@ namespace MaterialEditor
return false;
}
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id);
return true;
}
bool MaterialDocument::Rebuild()
bool MaterialDocument::Reopen()
{
// Store history and property changes that should be reapplied after reload
auto undoHistoryToRestore = m_undoHistory;
@@ -222,7 +208,7 @@ namespace MaterialEditor
RestorePropertyValues(propertyValuesToRestore);
AZStd::swap(undoHistoryToRestore, m_undoHistory);
AZStd::swap(undoHistoryIndexToRestore, m_undoHistoryIndex);
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id);
return true;
}
@@ -285,7 +271,7 @@ namespace MaterialEditor
AZ_TracePrintf("MaterialDocument", "Material document saved: '%s'.\n", m_absolutePath.data());
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentSaved, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id);
m_saveTriggeredInternally = true;
return true;
@@ -348,7 +334,7 @@ namespace MaterialEditor
AZ_TracePrintf("MaterialDocument", "Material document saved: '%s'.\n", normalizedSavePath.c_str());
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentSaved, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id);
// If the document is saved to a new file we need to reopen the new document to update assets, paths, property deltas.
if (!Open(normalizedSavePath))
@@ -424,7 +410,7 @@ namespace MaterialEditor
AZ_TracePrintf("MaterialDocument", "Material document saved: '%s'.\n", normalizedSavePath.c_str());
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentSaved, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id);
// If the document is saved to a new file we need to reopen the new document to update assets, paths, property deltas.
if (!Open(normalizedSavePath))
@@ -450,7 +436,7 @@ namespace MaterialEditor
AZ_TracePrintf("MaterialDocument", "Material document closed: '%s'.\n", m_absolutePath.c_str());
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentClosed, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id);
// Clearing after notification so paths are still available
Clear();
@@ -496,7 +482,7 @@ namespace MaterialEditor
// The history index is one beyond the last executed command. Decrement the index then execute undo.
m_undoHistory[--m_undoHistoryIndex].first();
AZ_TracePrintf("MaterialDocument", "Material document undo: '%s'.\n", m_absolutePath.c_str());
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
return true;
}
return false;
@@ -509,7 +495,7 @@ namespace MaterialEditor
// Execute the current redo command then move the history index to the next position.
m_undoHistory[m_undoHistoryIndex++].second();
AZ_TracePrintf("MaterialDocument", "Material document redo: '%s'.\n", m_absolutePath.c_str());
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
return true;
}
return false;
@@ -557,7 +543,7 @@ namespace MaterialEditor
// Assign the index to the end of history
m_undoHistoryIndex = aznumeric_cast<int>(m_undoHistory.size());
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
}
m_propertyValuesBeforeEdit.clear();
@@ -584,7 +570,7 @@ namespace MaterialEditor
if (!m_saveTriggeredInternally)
{
AZ_TracePrintf("MaterialDocument", "Material document changed externally: '%s'.\n", m_absolutePath.c_str());
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id);
}
m_saveTriggeredInternally = false;
}
@@ -595,7 +581,7 @@ namespace MaterialEditor
if (m_dependentAssetIds.find(asset->GetId()) != m_dependentAssetIds.end())
{
AZ_TracePrintf("MaterialDocument", "Material document dependency changed: '%s'.\n", m_absolutePath.c_str());
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id);
}
}
@@ -18,8 +18,7 @@
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/RPI.Public/Material/Material.h>
#include <Atom/Document/MaterialDocumentRequestBus.h>
#include <AtomToolsFramework/DynamicProperty/DynamicProperty.h>
#include <AtomToolsFramework/Document/AtomToolsDocument.h>
namespace MaterialEditor
{
@@ -27,7 +26,8 @@ namespace MaterialEditor
* MaterialDocument provides an API for modifying and saving material document properties.
*/
class MaterialDocument
: public MaterialDocumentRequestBus::Handler
: public AtomToolsFramework::AtomToolsDocument
, public MaterialDocumentRequestBus::Handler
, private AZ::TickBus::Handler
, private AZ::Data::AssetBus::MultiHandler
, private AzToolsFramework::AssetSystemBus::Handler
@@ -40,22 +40,15 @@ namespace MaterialEditor
MaterialDocument();
virtual ~MaterialDocument();
const AZ::Uuid& GetId() const;
////////////////////////////////////////////////////////////////////////
// MaterialDocumentRequestBus::Handler implementation
AZStd::string_view GetAbsolutePath() const override;
AZStd::string_view GetRelativePath() const override;
AZ::Data::Asset<AZ::RPI::MaterialAsset> GetAsset() const override;
AZ::Data::Instance<AZ::RPI::Material> GetInstance() const override;
const AZ::RPI::MaterialSourceData* GetMaterialSourceData() const override;
const AZ::RPI::MaterialTypeSourceData* GetMaterialTypeSourceData() const override;
// AtomToolsFramework::AtomToolsDocument
////////////////////////////////////////////////////////////////////////
const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const override;
const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const override;
bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override;
void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override;
bool Open(AZStd::string_view loadPath) override;
bool Rebuild() override;
bool Reopen() override;
bool Save() override;
bool SaveAsCopy(AZStd::string_view savePath) override;
bool SaveAsChild(AZStd::string_view savePath) override;
@@ -71,6 +64,14 @@ namespace MaterialEditor
bool EndEdit() override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// MaterialDocumentRequestBus::Handler implementation
AZ::Data::Asset<AZ::RPI::MaterialAsset> GetAsset() const override;
AZ::Data::Instance<AZ::RPI::Material> GetInstance() const override;
const AZ::RPI::MaterialSourceData* GetMaterialSourceData() const override;
const AZ::RPI::MaterialTypeSourceData* GetMaterialTypeSourceData() const override;
////////////////////////////////////////////////////////////////////////
private:
// Predicate for evaluating properties
@@ -130,21 +131,12 @@ namespace MaterialEditor
// @return names for the set of properties and groups that have been changed or need update.
EditorMaterialFunctorResult RunEditorMaterialFunctors(AZ::RPI::MaterialPropertyFlags dirtyFlags);
// Unique id of this material document
AZ::Uuid m_id = AZ::Uuid::CreateRandom();
// Underlying material asset
AZ::Data::Asset<AZ::RPI::MaterialAsset> m_materialAsset;
// Material instance being edited
AZ::Data::Instance<AZ::RPI::Material> m_materialInstance;
// Relative path to the material source file
AZStd::string m_relativePath;
// Absolute path to the material source file
AZStd::string m_absolutePath;
// Asset used to open document
AZ::Data::AssetId m_sourceAssetId;
@@ -7,10 +7,8 @@
*/
#include <Atom/Document/MaterialDocumentModule.h>
#include <Document/MaterialDocumentSystemComponent.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h>
#include <AzToolsFramework/Asset/AssetSystemComponent.h>
#include <Document/MaterialDocumentSystemComponent.h>
namespace MaterialEditor
{
@@ -18,7 +18,6 @@ namespace MaterialEditor
{
serializeContext->Class<MaterialDocumentSettings, AZ::UserSettings>()
->Version(1)
->Field("showReloadDocumentPrompt", &MaterialDocumentSettings::m_showReloadDocumentPrompt)
->Field("defaultMaterialTypeName", &MaterialDocumentSettings::m_defaultMaterialTypeName)
;
@@ -28,7 +27,6 @@ namespace MaterialEditor
"MaterialDocumentSettings", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialDocumentSettings::m_showReloadDocumentPrompt, "Show Reload Document Prompt", "")
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialDocumentSettings::m_defaultMaterialTypeName, "Default Material Type Name", "")
;
}
@@ -39,10 +37,9 @@ namespace MaterialEditor
behaviorContext->Class<MaterialDocumentSettings>("MaterialDocumentSettings")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "render")
->Attribute(AZ::Script::Attributes::Module, "materialeditor")
->Constructor()
->Constructor<const MaterialDocumentSettings&>()
->Property("showReloadDocumentPrompt", BehaviorValueProperty(&MaterialDocumentSettings::m_showReloadDocumentPrompt))
->Property("defaultMaterialTypeName", BehaviorValueProperty(&MaterialDocumentSettings::m_defaultMaterialTypeName))
;
}
@@ -6,40 +6,17 @@
*
*/
#include <Document/MaterialDocumentSystemComponent.h>
#include <Atom/Document/MaterialDocumentNotificationBus.h>
#include <Atom/Document/MaterialDocumentRequestBus.h>
#include <Atom/Document/MaterialDocumentSettings.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <AtomToolsFramework/Debug/TraceRecorder.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/Asset/AssetSystemBus.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/ViewPaneOptions.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QApplication>
#include <QFileDialog>
#include <QMessageBox>
#include <QString>
#include <QStyle>
AZ_POP_DISABLE_WARNING
#include <Document/MaterialDocument.h>
#include <Document/MaterialDocumentSystemComponent.h>
namespace MaterialEditor
{
MaterialDocumentSystemComponent::MaterialDocumentSystemComponent()
{
}
void MaterialDocumentSystemComponent::Reflect(AZ::ReflectContext* context)
{
MaterialDocumentSettings::Reflect(context);
@@ -53,7 +30,7 @@ namespace MaterialEditor
{
ec->Class<MaterialDocumentSystemComponent>("MaterialDocumentSystemComponent", "Tool for editing Atom material files")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System"))
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
;
}
@@ -61,66 +38,31 @@ namespace MaterialEditor
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<MaterialDocumentSystemRequestBus>("MaterialDocumentSystemRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "materialeditor")
->Event("CreateDocument", &MaterialDocumentSystemRequestBus::Events::CreateDocument)
->Event("DestroyDocument", &MaterialDocumentSystemRequestBus::Events::DestroyDocument)
->Event("OpenDocument", &MaterialDocumentSystemRequestBus::Events::OpenDocument)
->Event("CreateDocumentFromFile", &MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile)
->Event("CloseDocument", &MaterialDocumentSystemRequestBus::Events::CloseDocument)
->Event("CloseAllDocuments", &MaterialDocumentSystemRequestBus::Events::CloseAllDocuments)
->Event("CloseAllDocumentsExcept", &MaterialDocumentSystemRequestBus::Events::CloseAllDocumentsExcept)
->Event("SaveDocument", &MaterialDocumentSystemRequestBus::Events::SaveDocument)
->Event("SaveDocumentAsCopy", &MaterialDocumentSystemRequestBus::Events::SaveDocumentAsCopy)
->Event("SaveDocumentAsChild", &MaterialDocumentSystemRequestBus::Events::SaveDocumentAsChild)
->Event("SaveAllDocuments", &MaterialDocumentSystemRequestBus::Events::SaveAllDocuments)
;
behaviorContext->EBus<MaterialDocumentRequestBus>("MaterialDocumentRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "materialeditor")
->Event("GetAbsolutePath", &MaterialDocumentRequestBus::Events::GetAbsolutePath)
->Event("GetRelativePath", &MaterialDocumentRequestBus::Events::GetRelativePath)
->Event("GetPropertyValue", &MaterialDocumentRequestBus::Events::GetPropertyValue)
->Event("SetPropertyValue", &MaterialDocumentRequestBus::Events::SetPropertyValue)
->Event("Open", &MaterialDocumentRequestBus::Events::Open)
->Event("Rebuild", &MaterialDocumentRequestBus::Events::Rebuild)
->Event("Close", &MaterialDocumentRequestBus::Events::Close)
->Event("Save", &MaterialDocumentRequestBus::Events::Save)
->Event("SaveAsChild", &MaterialDocumentRequestBus::Events::SaveAsChild)
->Event("SaveAsCopy", &MaterialDocumentRequestBus::Events::SaveAsCopy)
->Event("IsOpen", &MaterialDocumentRequestBus::Events::IsOpen)
->Event("IsModified", &MaterialDocumentRequestBus::Events::IsModified)
->Event("IsSavable", &MaterialDocumentRequestBus::Events::IsSavable)
->Event("CanUndo", &MaterialDocumentRequestBus::Events::CanUndo)
->Event("CanRedo", &MaterialDocumentRequestBus::Events::CanRedo)
->Event("Undo", &MaterialDocumentRequestBus::Events::Undo)
->Event("Redo", &MaterialDocumentRequestBus::Events::Redo)
->Event("BeginEdit", &MaterialDocumentRequestBus::Events::BeginEdit)
->Event("EndEdit", &MaterialDocumentRequestBus::Events::EndEdit)
;
}
}
void MaterialDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc));
required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601));
required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad));
required.push_back(AZ_CRC("RPISystem", 0xf2add773));
required.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService"));
required.push_back(AZ_CRC_CE("AssetProcessorToolsConnection"));
required.push_back(AZ_CRC_CE("AssetDatabaseService"));
required.push_back(AZ_CRC_CE("PropertyManagerService"));
required.push_back(AZ_CRC_CE("RPISystem"));
}
void MaterialDocumentSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("MaterialDocumentSystemService"));
provided.push_back(AZ_CRC_CE("MaterialDocumentSystemService"));
}
void MaterialDocumentSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC("MaterialDocumentSystemService"));
incompatible.push_back(AZ_CRC_CE("MaterialDocumentSystemService"));
}
void MaterialDocumentSystemComponent::Init()
@@ -129,388 +71,15 @@ namespace MaterialEditor
void MaterialDocumentSystemComponent::Activate()
{
m_documentMap.clear();
m_settings = AZ::UserSettings::CreateFind<MaterialDocumentSettings>(AZ::Crc32("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL);
MaterialDocumentSystemRequestBus::Handler::BusConnect();
MaterialDocumentNotificationBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType,
[]()
{
return aznew MaterialDocument();
});
}
void MaterialDocumentSystemComponent::Deactivate()
{
AZ::TickBus::Handler::BusDisconnect();
MaterialDocumentNotificationBus::Handler::BusDisconnect();
MaterialDocumentSystemRequestBus::Handler::BusDisconnect();
m_documentMap.clear();
}
AZ::Uuid MaterialDocumentSystemComponent::CreateDocument()
{
auto document = AZStd::make_unique<MaterialDocument>();
if (!document)
{
AZ_Error("MaterialDocument", false, "Failed to create new document");
return AZ::Uuid::CreateNull();
}
AZ::Uuid documentId = document->GetId();
m_documentMap.emplace(documentId, document.release());
return documentId;
}
bool MaterialDocumentSystemComponent::DestroyDocument(const AZ::Uuid& documentId)
{
return m_documentMap.erase(documentId) != 0;
}
void MaterialDocumentSystemComponent::OnDocumentExternallyModified(const AZ::Uuid& documentId)
{
m_documentIdsToReopen.insert(documentId);
if (!AZ::TickBus::Handler::BusIsConnected())
{
AZ::TickBus::Handler::BusConnect();
}
}
void MaterialDocumentSystemComponent::OnDocumentDependencyModified(const AZ::Uuid& documentId)
{
m_documentIdsToRebuild.insert(documentId);
if (!AZ::TickBus::Handler::BusIsConnected())
{
AZ::TickBus::Handler::BusConnect();
}
}
void MaterialDocumentSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
{
for (const AZ::Uuid& documentId : m_documentIdsToReopen)
{
AZStd::string documentPath;
MaterialDocumentRequestBus::EventResult(documentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
if (m_settings->m_showReloadDocumentPrompt &&
(QMessageBox::question(QApplication::activeWindow(),
QString("Material document was externally modified"),
QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()),
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes))
{
continue;
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool openResult = false;
MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Open, documentPath);
if (!openResult)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Material document could not be opened"),
QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId);
}
}
for (const AZ::Uuid& documentId : m_documentIdsToRebuild)
{
AZStd::string documentPath;
MaterialDocumentRequestBus::EventResult(documentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
if (m_settings->m_showReloadDocumentPrompt &&
(QMessageBox::question(QApplication::activeWindow(),
QString("Material document dependencies have changed"),
QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()),
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes))
{
continue;
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool openResult = false;
MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Rebuild);
if (!openResult)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Material document could not be opened"),
QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId);
}
}
m_documentIdsToRebuild.clear();
m_documentIdsToReopen.clear();
AZ::TickBus::Handler::BusDisconnect();
}
AZ::Uuid MaterialDocumentSystemComponent::OpenDocument(AZStd::string_view sourcePath)
{
return OpenDocumentImpl(sourcePath, true);
}
AZ::Uuid MaterialDocumentSystemComponent::CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath)
{
const AZ::Uuid documentId = OpenDocumentImpl(sourcePath, false);
if (documentId.IsNull())
{
return AZ::Uuid::CreateNull();
}
if (!SaveDocumentAsChild(documentId, targetPath))
{
CloseDocument(documentId);
return AZ::Uuid::CreateNull();
}
// Send document open notification after creating new material
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentId);
return documentId;
}
bool MaterialDocumentSystemComponent::CloseDocument(const AZ::Uuid& documentId)
{
bool isOpen = false;
MaterialDocumentRequestBus::EventResult(isOpen, documentId, &MaterialDocumentRequestBus::Events::IsOpen);
if (!isOpen)
{
// immediately destroy unopened documents
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId);
return true;
}
AZStd::string documentPath;
MaterialDocumentRequestBus::EventResult(documentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
bool isModified = false;
MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified);
if (isModified)
{
auto selection = QMessageBox::question(QApplication::activeWindow(),
QString("Material document has unsaved changes"),
QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
if (selection == QMessageBox::Cancel)
{
AZ_TracePrintf("MaterialDocument", "Close document canceled: %s", documentPath.c_str());
return false;
}
if (selection == QMessageBox::Yes)
{
if (!SaveDocument(documentId))
{
AZ_Error("MaterialDocument", false, "Close document failed because document was not saved: %s", documentPath.c_str());
return false;
}
}
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool closeResult = true;
MaterialDocumentRequestBus::EventResult(closeResult, documentId, &MaterialDocumentRequestBus::Events::Close);
if (!closeResult)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Material document could not be closed"),
QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return false;
}
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId);
return true;
}
bool MaterialDocumentSystemComponent::CloseAllDocuments()
{
bool result = true;
auto documentMap = m_documentMap;
for (const auto& documentPair : documentMap)
{
if (!CloseDocument(documentPair.first))
{
result = false;
}
}
return result;
}
bool MaterialDocumentSystemComponent::CloseAllDocumentsExcept(const AZ::Uuid& documentId)
{
bool result = true;
auto documentMap = m_documentMap;
for (const auto& documentPair : documentMap)
{
if (documentPair.first != documentId)
{
if (!CloseDocument(documentPair.first))
{
result = false;
}
}
}
return result;
}
bool MaterialDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId)
{
AZStd::string saveMaterialPath;
MaterialDocumentRequestBus::EventResult(saveMaterialPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
if (saveMaterialPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveMaterialPath))
{
return false;
}
const QFileInfo saveInfo(saveMaterialPath.c_str());
if (saveInfo.exists() && !saveInfo.isWritable())
{
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be overwritten:\n%1").arg(saveMaterialPath.c_str()));
return false;
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool result = false;
MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::Save);
if (!result)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Material document could not be saved"),
QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return false;
}
return true;
}
bool MaterialDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath)
{
AZStd::string saveMaterialPath = targetPath;
if (saveMaterialPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveMaterialPath))
{
return false;
}
const QFileInfo saveInfo(saveMaterialPath.c_str());
if (saveInfo.exists() && !saveInfo.isWritable())
{
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be overwritten:\n%1").arg(saveMaterialPath.c_str()));
return false;
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool result = false;
MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsCopy, saveMaterialPath);
if (!result)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Material document could not be saved"),
QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return false;
}
return true;
}
bool MaterialDocumentSystemComponent::SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath)
{
AZStd::string saveMaterialPath = targetPath;
if (saveMaterialPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveMaterialPath))
{
return false;
}
const QFileInfo saveInfo(saveMaterialPath.c_str());
if (saveInfo.exists() && !saveInfo.isWritable())
{
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be overwritten:\n%1").arg(saveMaterialPath.c_str()));
return false;
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool result = false;
MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsChild, saveMaterialPath);
if (!result)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Material document could not be saved"),
QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return false;
}
return true;
}
bool MaterialDocumentSystemComponent::SaveAllDocuments()
{
bool result = true;
for (const auto& documentPair : m_documentMap)
{
if (!SaveDocument(documentPair.first))
{
result = false;
}
}
return result;
}
AZ::Uuid MaterialDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen)
{
AZStd::string requestedPath = sourcePath;
if (requestedPath.empty())
{
return AZ::Uuid::CreateNull();
}
if (!AzFramework::StringFunc::Path::Normalize(requestedPath))
{
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document path is invalid:\n%1").arg(requestedPath.c_str()));
return AZ::Uuid::CreateNull();
}
// Determine if the file is already open and select it
if (checkIfAlreadyOpen)
{
for (const auto& documentPair : m_documentMap)
{
AZStd::string openMaterialPath;
MaterialDocumentRequestBus::EventResult(openMaterialPath, documentPair.first, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
if (openMaterialPath == requestedPath)
{
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first);
return documentPair.first;
}
}
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
AZ::Uuid documentId = AZ::Uuid::CreateNull();
MaterialDocumentSystemRequestBus::BroadcastResult(documentId, &MaterialDocumentSystemRequestBus::Events::CreateDocument);
if (documentId.IsNull())
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Material document could not be created"),
QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return AZ::Uuid::CreateNull();
}
traceRecorder.GetDump().clear();
bool openResult = false;
MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Open, requestedPath);
if (!openResult)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Material document could not be opened"),
QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str()));
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId);
return AZ::Uuid::CreateNull();
}
return documentId;
}
}
@@ -9,34 +9,17 @@
#pragma once
#include <AzCore/Component/Component.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/Asset/AssetCommon.h>
#include <Atom/Document/MaterialDocumentNotificationBus.h>
#include <Atom/Document/MaterialDocumentSettings.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/RPI.Public/WindowContext.h>
#include <Document/MaterialDocument.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QFileInfo>
#include <QString>
AZ_POP_DISABLE_WARNING
namespace MaterialEditor
{
//! MaterialDocumentSystemComponent is the central component of the Material Editor Core gem
//! MaterialDocumentSystemComponent
class MaterialDocumentSystemComponent
: public AZ::Component
, private AZ::TickBus::Handler
, private MaterialDocumentNotificationBus::Handler
, private MaterialDocumentSystemRequestBus::Handler
{
public:
AZ_COMPONENT(MaterialDocumentSystemComponent, "{58ABE0AE-2710-41E2-ADFD-E2D67407427D}");
AZ_COMPONENT(MaterialDocumentSystemComponent, "{E011DA51-855D-45FA-87A3-1C1CD6379091}");
MaterialDocumentSystemComponent();
MaterialDocumentSystemComponent() = default;
~MaterialDocumentSystemComponent() = default;
MaterialDocumentSystemComponent(const MaterialDocumentSystemComponent&) = delete;
MaterialDocumentSystemComponent& operator=(const MaterialDocumentSystemComponent&) = delete;
@@ -54,39 +37,5 @@ namespace MaterialEditor
void Activate() override;
void Deactivate() override;
////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// MaterialDocumentNotificationBus::Handler overrides...
void OnDocumentDependencyModified(const AZ::Uuid& documentId) override;
void OnDocumentExternallyModified(const AZ::Uuid& documentId) override;
//////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// AZ::TickBus::Handler overrides...
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// MaterialDocumentSystemRequestBus::Handler overrides...
AZ::Uuid CreateDocument() override;
bool DestroyDocument(const AZ::Uuid& documentId) override;
AZ::Uuid OpenDocument(AZStd::string_view sourcePath) override;
AZ::Uuid CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) override;
bool CloseDocument(const AZ::Uuid& documentId) override;
bool CloseAllDocuments() override;
bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) override;
bool SaveDocument(const AZ::Uuid& documentId) override;
bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) override;
bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) override;
bool SaveAllDocuments() override;
////////////////////////////////////////////////////////////////////////
AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen);
AZStd::intrusive_ptr<MaterialDocumentSettings> m_settings;
AZStd::unordered_map<AZ::Uuid, AZStd::shared_ptr<MaterialDocument>> m_documentMap;
AZStd::unordered_set<AZ::Uuid> m_documentIdsToRebuild;
AZStd::unordered_set<AZ::Uuid> m_documentIdsToReopen;
const size_t m_maxMessageBoxLineCount = 15;
};
} // namespace MaterialEditor
@@ -7,9 +7,9 @@
*/
#include <Atom/Document/MaterialDocumentModule.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/Viewport/MaterialViewportModule.h>
#include <Atom/Window/MaterialEditorWindowModule.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <MaterialEditorApplication.h>
#include <MaterialEditor_Traits_Platform.h>
@@ -68,7 +68,7 @@ namespace MaterialEditor
const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex);
AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str());
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
}
Base::ProcessCommandLine(commandLine);
@@ -8,8 +8,8 @@
#pragma once
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Application/AtomToolsApplication.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
namespace MaterialEditor
{
@@ -243,7 +243,7 @@ namespace MaterialEditor
OnFieldOfViewChanged(viewportSettings->m_fieldOfView);
OnDisplayMapperOperationTypeChanged(viewportSettings->m_displayMapperOperationType);
MaterialDocumentNotificationBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect();
MaterialViewportNotificationBus::Handler::BusConnect();
AZ::TickBus::Handler::BusConnect();
AZ::TransformNotificationBus::MultiHandler::BusConnect(m_cameraEntity->GetId());
@@ -255,7 +255,7 @@ namespace MaterialEditor
AzFramework::WindowSystemRequestBus::Handler::BusDisconnect();
AZ::TransformNotificationBus::MultiHandler::BusDisconnect();
AZ::TickBus::Handler::BusDisconnect();
MaterialDocumentNotificationBus::Handler::BusDisconnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
MaterialViewportNotificationBus::Handler::BusDisconnect();
AZ::Data::AssetBus::Handler::BusDisconnect();
@@ -8,16 +8,14 @@
#pragma once
#include <AzCore/Component/TickBus.h>
#include <AzCore/Component/TransformBus.h>
#include <AtomCore/Instance/Instance.h>
#include <Atom/RPI.Public/Base.h>
#include <Atom/Document/MaterialDocumentNotificationBus.h>
#include <Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h>
#include <Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h>
#include <Atom/RPI.Public/Base.h>
#include <Atom/Viewport/MaterialViewportNotificationBus.h>
#include <AtomCore/Instance/Instance.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/Component/TransformBus.h>
#include <AzFramework/Windowing/WindowBus.h>
#include <Viewport/InputController/MaterialEditorViewportInputController.h>
@@ -45,7 +43,7 @@ namespace MaterialEditor
class MaterialViewportRenderer
: public AZ::Data::AssetBus::Handler
, public AZ::TickBus::Handler
, public MaterialDocumentNotificationBus::Handler
, public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
, public MaterialViewportNotificationBus::Handler
, public AZ::TransformNotificationBus::MultiHandler
, public AzFramework::WindowSystemRequestBus::Handler
@@ -60,7 +58,7 @@ namespace MaterialEditor
private:
// MaterialDocumentNotificationBus::Handler interface overrides...
// AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler interface overrides...
void OnDocumentOpened(const AZ::Uuid& documentId) override;
// MaterialViewportNotificationBus::Handler interface overrides...
@@ -54,7 +54,7 @@ namespace MaterialEditor
behaviorContext->Class<MaterialViewportSettings>("MaterialViewportSettings")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "render")
->Attribute(AZ::Script::Attributes::Module, "materialeditor")
->Constructor()
->Constructor<const MaterialViewportSettings&>()
->Property("enableGrid", BehaviorValueProperty(&MaterialViewportSettings::m_enableGrid))
@@ -7,9 +7,12 @@
*/
#include <Atom/Document/MaterialDocumentRequestBus.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
@@ -18,9 +21,8 @@
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
#include <AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h>
#include <Source/Window/MaterialBrowserWidget.h>
#include <Source/Window/ui_MaterialBrowserWidget.h>
#include <Window/MaterialBrowserWidget.h>
#include <Window/ui_MaterialBrowserWidget.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QAction>
@@ -91,14 +93,14 @@ namespace MaterialEditor
}
});
MaterialDocumentNotificationBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect();
}
MaterialBrowserWidget::~MaterialBrowserWidget()
{
// Maintains the tree expansion state between runs
m_ui->m_assetBrowserTreeViewWidget->SaveState();
MaterialDocumentNotificationBus::Handler::BusDisconnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
AZ::TickBus::Handler::BusDisconnect();
}
@@ -144,13 +146,13 @@ namespace MaterialEditor
{
if (entry)
{
if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension))
if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialSourceData::Extension))
{
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath());
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath());
}
else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension))
else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialTypeSourceData::Extension))
{
//ignore MaterialTypeExtension
//ignore AZ::RPI::MaterialTypeSourceData::Extension
}
else
{
@@ -163,7 +165,7 @@ namespace MaterialEditor
void MaterialBrowserWidget::OnDocumentOpened(const AZ::Uuid& documentId)
{
AZStd::string absolutePath;
MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (!absolutePath.empty())
{
// Selecting a new asset in the browser is not guaranteed to happen immediately.
@@ -230,4 +232,4 @@ namespace MaterialEditor
} // namespace MaterialEditor
#include <Source/Window/moc_MaterialBrowserWidget.cpp>
#include <Window/moc_MaterialBrowserWidget.cpp>
@@ -9,15 +9,15 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <Atom/Document/MaterialDocumentNotificationBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AzCore/Component/TickBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QWidget>
#include <QByteArray>
#include <QWidget>
AZ_POP_DISABLE_WARNING
#endif
@@ -45,7 +45,7 @@ namespace MaterialEditor
class MaterialBrowserWidget
: public QWidget
, protected AZ::TickBus::Handler
, protected MaterialDocumentNotificationBus::Handler
, protected AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
{
Q_OBJECT
public:
@@ -56,7 +56,7 @@ namespace MaterialEditor
AzToolsFramework::AssetBrowser::FilterConstType CreateFilter() const;
void OpenSelectedEntries();
// MaterialDocumentNotificationBus::Handler implementation
// AtomToolsDocumentNotificationBus::Handler implementation
void OnDocumentOpened(const AZ::Uuid& documentId) override;
// AZ::TickBus::Handler
@@ -6,32 +6,28 @@
*
*/
#include <QApplication>
#include <QClipboard>
#include <QMenu>
#include <QInputDialog>
#include <QMessageBox>
#include <QFileDialog>
#include <QDesktopServices>
#include <AzCore/std/string/wildcard.h>
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/Thumbnails/SourceControlThumbnail.h>
#include <AtomToolsFramework/Util/Util.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Window/MaterialEditorBrowserInteractions.h>
#include <Window/CreateMaterialDialog/CreateMaterialDialog.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzCore/std/string/wildcard.h>
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/Thumbnails/SourceControlThumbnail.h>
#include <Window/CreateMaterialDialog/CreateMaterialDialog.h>
#include <Window/MaterialEditorBrowserInteractions.h>
#include <QApplication>
#include <QClipboard>
#include <QDesktopServices>
#include <QFileDialog>
#include <QInputDialog>
#include <QMenu>
#include <QMessageBox>
namespace MaterialEditor
{
@@ -66,11 +62,11 @@ namespace MaterialEditor
if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source)
{
const auto source = azalias_cast<const SourceAssetBrowserEntry*>(entry);
if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension))
if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialSourceData::Extension))
{
AddContextMenuActionsForMaterialSource(caller, menu, source);
}
else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension))
else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialTypeSourceData::Extension))
{
AddContextMenuActionsForMaterialTypeSource(caller, menu, source);
}
@@ -115,7 +111,7 @@ namespace MaterialEditor
AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." +
AZ::RPI::MaterialSourceData::Extension).absoluteFilePath();
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile,
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile,
entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData());
});
@@ -157,7 +153,7 @@ namespace MaterialEditor
{
menu->addAction("Open", [entry]()
{
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath());
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath());
});
menu->addAction("Duplicate...", [entry, caller]()
@@ -191,7 +187,7 @@ namespace MaterialEditor
AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." +
AZ::RPI::MaterialSourceData::Extension).absoluteFilePath();
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile,
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile,
entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData());
});
@@ -258,7 +254,7 @@ namespace MaterialEditor
!createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() &&
!createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty())
{
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile,
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile,
createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData(),
createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData());
}
@@ -6,7 +6,11 @@
*
*/
#include <Atom/Document/MaterialDocumentRequestBus.h>
#include <Atom/RHI/Factory.h>
#include <Atom/Window/MaterialEditorWindowSettings.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h>
#include <AzFramework/StringFunc/StringFunc.h>
@@ -15,11 +19,6 @@
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
#include <Atom/Document/MaterialDocumentRequestBus.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/Window/MaterialEditorWindowSettings.h>
#include <Viewport/MaterialViewportWidget.h>
#include <Window/CreateMaterialDialog/CreateMaterialDialog.h>
#include <Window/HelpDialog/HelpDialog.h>
@@ -106,13 +105,13 @@ namespace MaterialEditor
m_advancedDockManager->restoreState(windowState);
}
MaterialDocumentNotificationBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect();
OnDocumentOpened(AZ::Uuid::CreateNull());
}
MaterialEditorWindow::~MaterialEditorWindow()
{
MaterialDocumentNotificationBus::Handler::BusDisconnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
}
@@ -150,7 +149,7 @@ namespace MaterialEditor
void MaterialEditorWindow::closeEvent(QCloseEvent* closeEvent)
{
bool didClose = true;
MaterialDocumentSystemRequestBus::BroadcastResult(didClose, &MaterialDocumentSystemRequestBus::Events::CloseAllDocuments);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(didClose, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
if (!didClose)
{
closeEvent->ignore();
@@ -171,17 +170,17 @@ namespace MaterialEditor
void MaterialEditorWindow::OnDocumentOpened(const AZ::Uuid& documentId)
{
bool isOpen = false;
MaterialDocumentRequestBus::EventResult(isOpen, documentId, &MaterialDocumentRequestBus::Events::IsOpen);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsOpen);
bool isSavable = false;
MaterialDocumentRequestBus::EventResult(isSavable, documentId, &MaterialDocumentRequestBus::Events::IsSavable);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isSavable, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsSavable);
bool isModified = false;
MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified);
bool canUndo = false;
MaterialDocumentRequestBus::EventResult(canUndo, documentId, &MaterialDocumentRequestBus::Events::CanUndo);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo);
bool canRedo = false;
MaterialDocumentRequestBus::EventResult(canRedo, documentId, &MaterialDocumentRequestBus::Events::CanRedo);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo);
AZStd::string absolutePath;
MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
@@ -238,7 +237,7 @@ namespace MaterialEditor
const QString documentPath = GetDocumentPath(documentId);
if (!documentPath.isEmpty())
{
const QString status = QString("Document closed: %1").arg(documentPath);
const QString status = QString("Document opened: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"White\">%1</font>").arg(status));
}
}
@@ -255,9 +254,9 @@ namespace MaterialEditor
void MaterialEditorWindow::OnDocumentModified(const AZ::Uuid& documentId)
{
bool isModified = false;
MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified);
AZStd::string absolutePath;
MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
@@ -268,9 +267,9 @@ namespace MaterialEditor
if (documentId == GetDocumentIdFromTab(m_tabWidget->currentIndex()))
{
bool canUndo = false;
MaterialDocumentRequestBus::EventResult(canUndo, documentId, &MaterialDocumentRequestBus::Events::CanUndo);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo);
bool canRedo = false;
MaterialDocumentRequestBus::EventResult(canRedo, documentId, &MaterialDocumentRequestBus::Events::CanRedo);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo);
m_actionUndo->setEnabled(canUndo);
m_actionRedo->setEnabled(canRedo);
}
@@ -279,15 +278,15 @@ namespace MaterialEditor
void MaterialEditorWindow::OnDocumentSaved(const AZ::Uuid& documentId)
{
bool isModified = false;
MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified);
AZStd::string absolutePath;
MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
const QString documentPath = GetDocumentPath(documentId);
const QString status = QString("Document closed: %1").arg(documentPath);
const QString status = QString("Document saved: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"White\">%1</font>").arg(status));
}
@@ -306,7 +305,7 @@ namespace MaterialEditor
!createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() &&
!createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty())
{
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile,
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile,
createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData(),
createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData());
}
@@ -317,7 +316,7 @@ namespace MaterialEditor
const AZStd::string filePath = AtomToolsFramework::GetOpenFileInfo(assetTypes).absoluteFilePath().toUtf8().constData();
if (!filePath.empty())
{
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, filePath);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, filePath);
}
}, QKeySequence::Open);
@@ -328,11 +327,11 @@ namespace MaterialEditor
m_actionSave = m_menuFile->addAction("&Save", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
bool result = false;
MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveDocument, documentId);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId);
if (!result)
{
const QString documentPath = GetDocumentPath(documentId);
const QString status = QString("Failed to save document: %1").arg(documentPath);
const QString status = QString("Document save failed: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(status));
}
}, QKeySequence::Save);
@@ -342,11 +341,11 @@ namespace MaterialEditor
const QString documentPath = GetDocumentPath(documentId);
bool result = false;
MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveDocumentAsCopy,
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy,
documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
if (!result)
{
const QString status = QString("Failed to save document: %1").arg(documentPath);
const QString status = QString("Document save failed: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(status));
}
}, QKeySequence::SaveAs);
@@ -356,21 +355,21 @@ namespace MaterialEditor
const QString documentPath = GetDocumentPath(documentId);
bool result = false;
MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveDocumentAsChild,
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsChild,
documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
if (!result)
{
const QString status = QString("Failed to save document: %1").arg(documentPath);
const QString status = QString("Document save failed: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(status));
}
});
m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() {
bool result = false;
MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveAllDocuments);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments);
if (!result)
{
const QString status = QString("Failed to save documents.");
const QString status = QString("Document save all failed.");
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(status));
}
});
@@ -379,16 +378,16 @@ namespace MaterialEditor
m_actionClose = m_menuFile->addAction("&Close", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
}, QKeySequence::Close);
m_actionCloseAll = m_menuFile->addAction("Close All", [this]() {
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseAllDocuments);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
});
m_actionCloseOthers = m_menuFile->addAction("Close Others", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
});
m_menuFile->addSeparator();
@@ -412,11 +411,11 @@ namespace MaterialEditor
m_actionUndo = m_menuEdit->addAction("&Undo", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
bool result = false;
MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::Undo);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Undo);
if (!result)
{
const QString documentPath = GetDocumentPath(documentId);
const QString status = QString("Failed to perform undo on document: %1").arg(documentPath);
const QString status = QString("Document undo failed: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(status));
}
}, QKeySequence::Undo);
@@ -424,11 +423,11 @@ namespace MaterialEditor
m_actionRedo = m_menuEdit->addAction("&Redo", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
bool result = false;
MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::Redo);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Redo);
if (!result)
{
const QString documentPath = GetDocumentPath(documentId);
const QString status = QString("Failed to perform redo on document: %1").arg(documentPath);
const QString status = QString("Document redo failed: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(status));
}
}, QKeySequence::Redo);
@@ -501,19 +500,19 @@ namespace MaterialEditor
// This should automatically clear the active document
connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) {
const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentId);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
});
connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) {
const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
});
}
QString MaterialEditorWindow::GetDocumentPath(const AZ::Uuid& documentId) const
{
AZStd::string absolutePath;
MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Handler::GetAbsolutePath);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Handler::GetAbsolutePath);
return absolutePath.c_str();
}
@@ -529,15 +528,15 @@ namespace MaterialEditor
const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select";
tabMenu.addAction(selectActionName, [this, clickedTabIndex]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex);
MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentId);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
});
tabMenu.addAction("Close", [this, clickedTabIndex]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex);
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
});
auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex);
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
});
closeOthersAction->setEnabled(tabBar->count() > 1);
tabMenu.exec(QCursor::pos());
@@ -9,7 +9,7 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <Atom/Document/MaterialDocumentNotificationBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindow.h>
#include <AzCore/Memory/SystemAllocator.h>
@@ -30,7 +30,7 @@ namespace MaterialEditor
*/
class MaterialEditorWindow
: public AtomToolsFramework::AtomToolsMainWindow
, private MaterialDocumentNotificationBus::Handler
, private AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
{
Q_OBJECT
public:
@@ -46,7 +46,7 @@ namespace MaterialEditor
void LockViewportRenderTargetSize(uint32_t width, uint32_t height) override;
void UnlockViewportRenderTargetSize() override;
// MaterialDocumentNotificationBus::Handler overrides...
// AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler overrides...
void OnDocumentOpened(const AZ::Uuid& documentId) override;
void OnDocumentClosed(const AZ::Uuid& documentId) override;
void OnDocumentModified(const AZ::Uuid& documentId) override;
@@ -37,7 +37,7 @@ namespace MaterialEditor
behaviorContext->Class<MaterialEditorWindowSettings>("MaterialEditorWindowSettings")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "render")
->Attribute(AZ::Script::Attributes::Module, "materialeditor")
->Constructor()
->Constructor<const MaterialEditorWindowSettings&>()
;
@@ -6,17 +6,15 @@
*
*/
#include <Atom/Document/MaterialDocumentRequestBus.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Material/MaterialPropertyId.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
#include <Atom/Document/MaterialDocumentRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
#include <AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h>
#include <AtomToolsFramework/Inspector/InspectorPropertyGroupWidget.h>
#include <AtomToolsFramework/Util/MaterialPropertyUtil.h>
#include <Window/MaterialInspector/MaterialInspector.h>
namespace MaterialEditor
@@ -27,12 +25,12 @@ namespace MaterialEditor
m_windowSettings = AZ::UserSettings::CreateFind<MaterialEditorWindowSettings>(
AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL);
MaterialDocumentNotificationBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect();
}
MaterialInspector::~MaterialInspector()
{
MaterialDocumentNotificationBus::Handler::BusDisconnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect();
}
@@ -69,9 +67,9 @@ namespace MaterialEditor
m_documentId = documentId;
bool isOpen = false;
MaterialDocumentRequestBus::EventResult(isOpen, m_documentId, &MaterialDocumentRequestBus::Events::IsOpen);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isOpen, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsOpen);
MaterialDocumentRequestBus::EventResult(m_documentPath, m_documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(m_documentPath, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (!m_documentId.IsNull() && isOpen)
{
@@ -113,13 +111,13 @@ namespace MaterialEditor
auto& group = m_groups[groupNameId];
AtomToolsFramework::DynamicProperty property;
MaterialDocumentRequestBus::EventResult(
property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("overview.materialType"));
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty, AZ::Name("overview.materialType"));
group.m_properties.push_back(property);
property = {};
MaterialDocumentRequestBus::EventResult(
property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("overview.parentMaterial"));
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty, AZ::Name("overview.parentMaterial"));
group.m_properties.push_back(property);
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
@@ -145,8 +143,8 @@ namespace MaterialEditor
for (const auto& uvNamePair : uvNameMap)
{
AtomToolsFramework::DynamicProperty property;
MaterialDocumentRequestBus::EventResult(
property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty,
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty,
AZ::RPI::MaterialPropertyId(groupNameId, uvNamePair.m_shaderInput.ToString()).GetFullName());
group.m_properties.push_back(property);
@@ -182,8 +180,8 @@ namespace MaterialEditor
for (const auto& propertyDefinition : propertyListItr->second)
{
AtomToolsFramework::DynamicProperty property;
MaterialDocumentRequestBus::EventResult(
property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty,
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty,
AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName());
group.m_properties.push_back(property);
}
@@ -196,8 +194,8 @@ namespace MaterialEditor
AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget);
bool isGroupVisible = false;
MaterialDocumentRequestBus::EventResult(
isGroupVisible, m_documentId, &MaterialDocumentRequestBus::Events::IsPropertyGroupVisible, AZ::Name{groupNameId});
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
isGroupVisible, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsPropertyGroupVisible, AZ::Name{groupNameId});
SetGroupVisible(groupNameId, isGroupVisible);
}
}
@@ -264,7 +262,7 @@ namespace MaterialEditor
if (m_activeProperty != property)
{
m_activeProperty = property;
MaterialDocumentRequestBus::Event(m_documentId, &MaterialDocumentRequestBus::Events::BeginEdit);
AtomToolsFramework::AtomToolsDocumentRequestBus::Event(m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::BeginEdit);
}
}
}
@@ -276,8 +274,8 @@ namespace MaterialEditor
{
if (m_activeProperty == property)
{
MaterialDocumentRequestBus::Event(
m_documentId, &MaterialDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue());
AtomToolsFramework::AtomToolsDocumentRequestBus::Event(
m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue());
}
}
}
@@ -292,10 +290,10 @@ namespace MaterialEditor
{
if (m_activeProperty == property)
{
MaterialDocumentRequestBus::Event(
m_documentId, &MaterialDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue());
AtomToolsFramework::AtomToolsDocumentRequestBus::Event(
m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue());
MaterialDocumentRequestBus::Event(m_documentId, &MaterialDocumentRequestBus::Events::EndEdit);
AtomToolsFramework::AtomToolsDocumentRequestBus::Event(m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::EndEdit);
m_activeProperty = nullptr;
}
}
@@ -9,14 +9,12 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/std/containers/unordered_map.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h>
#include <Atom/Window/MaterialEditorWindowSettings.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h>
#include <AtomToolsFramework/Inspector/InspectorWidget.h>
#include <Atom/Document/MaterialDocumentNotificationBus.h>
#include <Atom/Window/MaterialEditorWindowSettings.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h>
#endif
namespace MaterialEditor
@@ -25,7 +23,7 @@ namespace MaterialEditor
//! The settings can be divided into cards, with each one showing a subset of properties.
class MaterialInspector
: public AtomToolsFramework::InspectorWidget
, public MaterialDocumentNotificationBus::Handler
, public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
, public AzToolsFramework::IPropertyEditorNotify
{
Q_OBJECT
@@ -52,7 +50,7 @@ namespace MaterialEditor
void AddUvNamesGroup();
void AddPropertiesGroup();
// MaterialDocumentNotificationBus::Handler implementation
// AtomToolsDocumentNotificationBus::Handler implementation
void OnDocumentOpened(const AZ::Uuid& documentId) override;
void OnDocumentPropertyValueModified(const AZ::Uuid& documentId, const AtomToolsFramework::DynamicProperty& property) override;
void OnDocumentPropertyConfigModified(const AZ::Uuid& documentId, const AtomToolsFramework::DynamicProperty& property) override;
@@ -15,7 +15,9 @@ namespace MaterialEditor
: AtomToolsFramework::InspectorWidget(parent)
{
m_documentSettings =
AZ::UserSettings::CreateFind<MaterialDocumentSettings>(AZ::Crc32("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL);
AZ::UserSettings::CreateFind<MaterialDocumentSettings>(AZ_CRC_CE("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL);
m_documentSystemSettings = AZ::UserSettings::CreateFind<AtomToolsFramework::AtomToolsDocumentSystemSettings>(
AZ_CRC_CE("AtomToolsDocumentSystemSettings"), AZ::UserSettings::CT_GLOBAL);
}
SettingsWidget::~SettingsWidget()
@@ -26,23 +28,37 @@ namespace MaterialEditor
void SettingsWidget::Populate()
{
AddGroupsBegin();
AddDocumentGroup();
AddDocumentSystemSettingsGroup();
AddDocumentSettingsGroup();
AddGroupsEnd();
}
void SettingsWidget::AddDocumentGroup()
void SettingsWidget::AddDocumentSettingsGroup()
{
const AZStd::string groupNameId = "documentSettings";
const AZStd::string groupDisplayName = "Document Settings";
const AZStd::string groupDescription = "Document Settings";
const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentGroup"));
const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSettingsGroup"));
AddGroup(
groupNameId, groupDisplayName, groupDescription,
new AtomToolsFramework::InspectorPropertyGroupWidget(
m_documentSettings.get(), nullptr, m_documentSettings->TYPEINFO_Uuid(), this, this, saveStateKey));
}
void SettingsWidget::AddDocumentSystemSettingsGroup()
{
const AZStd::string groupNameId = "documentSystemSettings";
const AZStd::string groupDisplayName = "Document System Settings";
const AZStd::string groupDescription = "Document System Settings";
const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSystemSettingsGroup"));
AddGroup(
groupNameId, groupDisplayName, groupDescription,
new AtomToolsFramework::InspectorPropertyGroupWidget(
m_documentSystemSettings.get(), nullptr, m_documentSystemSettings->TYPEINFO_Uuid(), this, this, saveStateKey));
}
void SettingsWidget::Reset()
{
AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect();
@@ -10,6 +10,7 @@
#if !defined(Q_MOC_RUN)
#include <Atom/Document/MaterialDocumentSettings.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h>
#include <AtomToolsFramework/Inspector/InspectorWidget.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h>
#endif
@@ -31,7 +32,8 @@ namespace MaterialEditor
void Populate();
private:
void AddDocumentGroup();
void AddDocumentSettingsGroup();
void AddDocumentSystemSettingsGroup();
// AtomToolsFramework::InspectorRequestBus::Handler overrides...
void Reset() override;
@@ -46,5 +48,6 @@ namespace MaterialEditor
void PropertySelectionChanged(AzToolsFramework::InstanceDataNode*, bool) override {}
AZStd::intrusive_ptr<MaterialDocumentSettings> m_documentSettings;
AZStd::intrusive_ptr<AtomToolsFramework::AtomToolsDocumentSystemSettings> m_documentSystemSettings;
};
} // namespace MaterialEditor
@@ -8,8 +8,6 @@
set(FILES
Include/Atom/Document/MaterialDocumentModule.h
Include/Atom/Document/MaterialDocumentSystemRequestBus.h
Include/Atom/Document/MaterialDocumentNotificationBus.h
Include/Atom/Document/MaterialDocumentRequestBus.h
Include/Atom/Document/MaterialDocumentSettings.h
Source/Document/MaterialDocumentModule.cpp
@@ -93,11 +93,11 @@ def ToRadians(degrees):
return 3.14159 * degrees / 180.0;
def OpenMaterial(filename):
documentId = azlmbr.materialeditor.MaterialDocumentSystemRequestBus(azlmbr.bus.Broadcast, 'OpenDocument', os.path.join(g_materialTestFolder, filename))
documentId = azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(azlmbr.bus.Broadcast, 'OpenDocument', os.path.join(g_materialTestFolder, filename))
return documentId
def CloseMaterial(documentId):
azlmbr.materialeditor.MaterialDocumentSystemRequestBus(azlmbr.bus.Broadcast, 'CloseDocument', documentId)
azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(azlmbr.bus.Broadcast, 'CloseDocument', documentId)
def SelectLightingPreset(presetName):
azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, 'SelectLightingPresetByName', presetName)
@@ -1,56 +0,0 @@
/*
* 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
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/std/any.h>
namespace ShaderManagementConsole
{
class ShaderManagementConsoleDocumentNotifications
: public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
//! Signal that a document was created
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentCreated([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a document was destroyed
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentDestroyed([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a document was opened
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentOpened([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a document was closed
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentClosed([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a document was saved
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentSaved([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a document was selected
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentSelected([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a document was modified
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentModified([[maybe_unused]] const AZ::Uuid& documentId) {}
//! Signal that a document undo state was updated
//! @param documentId unique id of document for which the notification is sent
virtual void OnDocumentUndoStateChanged([[maybe_unused]] const AZ::Uuid& documentId) {}
};
using ShaderManagementConsoleDocumentNotificationBus = AZ::EBus<ShaderManagementConsoleDocumentNotifications>;
} // namespace ShaderManagementConsole
@@ -7,18 +7,13 @@
*/
#pragma once
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Outcome/Outcome.h>
#include <AzCore/std/any.h>
#include <AzCore/std/string/string_view.h>
#include <Atom/RPI.Reflect/Shader/ShaderOptionGroupLayout.h>
#include <Atom/RPI.Edit/Shader/ShaderSourceData.h>
#include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h>
#include <Atom/RPI.Reflect/Shader/ShaderOptionGroupLayout.h>
#include <AzCore/Asset/AssetCommon.h>
namespace ShaderManagementConsole
{
using ShaderManagementConsoleDocumentResult = AZ::Outcome<AZStd::string, AZStd::string>;
class ShaderManagementConsoleDocumentRequests
: public AZ::EBusTraits
@@ -28,12 +23,6 @@ namespace ShaderManagementConsole
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
typedef AZ::Uuid BusIdType;
//! Get absolute path of document
virtual AZStd::string_view GetAbsolutePath() const = 0;
//! Get relative path of document
virtual AZStd::string_view GetRelativePath() const = 0;
//! Get the number of options
virtual size_t GetShaderOptionCount() const = 0;
@@ -45,47 +34,6 @@ namespace ShaderManagementConsole
//! Get the information for the shader variant at the specified index
virtual const AZ::RPI::ShaderVariantListSourceData::VariantInfo& GetShaderVariantInfo(size_t index) const = 0;
//! Load document and related data
//! @param loadPath Absolute path of document to load
virtual ShaderManagementConsoleDocumentResult Open(AZStd::string_view loadPath) = 0;
//! Save document to file
virtual ShaderManagementConsoleDocumentResult Save() = 0;
//! Save document copy
//! @param savePath Absolute path where document is saved
virtual ShaderManagementConsoleDocumentResult SaveAsCopy(AZStd::string_view savePath) = 0;
//! Close document and reset its data
virtual ShaderManagementConsoleDocumentResult Close() = 0;
//! document is loaded
virtual bool IsOpen() const = 0;
//! document has changes pending
virtual bool IsModified() const = 0;
//! Can the document be saved
virtual bool IsSavable() const = 0;
//! Returns true if there are reversible modifications to the document
virtual bool CanUndo() const = 0;
//! Returns true if there are changes that were reversed and can be re-applied to the document
virtual bool CanRedo() const = 0;
//! Restores the previous state of the document
virtual bool Undo() = 0;
//! Restores the next state of the document
virtual bool Redo() = 0;
//! Signal that editing is about to begin, like beginning to drag a slider control
virtual bool BeginEdit() = 0;
//! Signal that editing has completed, like after releasing the mouse button after continuously dragging a slider control
virtual bool EndEdit() = 0;
};
using ShaderManagementConsoleDocumentRequestBus = AZ::EBus<ShaderManagementConsoleDocumentRequests>;
@@ -1,57 +0,0 @@
/*
* 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
#include <AzCore/EBus/EBus.h>
namespace ShaderManagementConsole
{
//! ShaderManagementConsoleDocumentSystemRequestBus provides high level file requests for menus, scripts, etc.
class ShaderManagementConsoleDocumentSystemRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//! Create a document object
//! @return Uuid of new document, or null Uuid if failed
virtual AZ::Uuid CreateDocument() = 0;
//! Destroy a document object with the specified id
//! @return true if Uuid was found and removed, otherwise false
virtual bool DestroyDocument(const AZ::Uuid& documentId) = 0;
//! Open a document for editing
//! @param path document to edit.
//! @return unique id of new document if successful, otherwise null Uuid
virtual AZ::Uuid OpenDocument(AZStd::string_view path) = 0;
//! Close the specified document
//! @param documentId unique id of document to close
virtual bool CloseDocument(const AZ::Uuid& documentId) = 0;
//! Close all documents
virtual bool CloseAllDocuments() = 0;
//! Save the specified document
//! @param documentId unique id of document to save
virtual bool SaveDocument(const AZ::Uuid& documentId) = 0;
//! Save the specified document to a different file
//! @param documentId unique id of document to save
virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId) = 0;
//! Save all documents
virtual bool SaveAllDocuments() = 0;
};
using ShaderManagementConsoleDocumentSystemRequestBus = AZ::EBus<ShaderManagementConsoleDocumentSystemRequests>;
} // namespace ShaderManagementConsole
@@ -8,48 +8,32 @@
#include <Atom/RPI.Edit/Common/JsonUtils.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <Document/ShaderManagementConsoleDocument.h>
#include <Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
#include <Document/ShaderManagementConsoleDocument.h>
namespace ShaderManagementConsole
{
ShaderManagementConsoleDocument::ShaderManagementConsoleDocument()
: AtomToolsFramework::AtomToolsDocument()
{
ShaderManagementConsoleDocumentRequestBus::Handler::BusConnect(m_id);
ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentCreated, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id);
}
ShaderManagementConsoleDocument::~ShaderManagementConsoleDocument()
{
ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentDestroyed, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id);
ShaderManagementConsoleDocumentRequestBus::Handler::BusDisconnect();
}
const AZ::Uuid& ShaderManagementConsoleDocument::GetId() const
{
return m_id;
}
AZStd::string_view ShaderManagementConsoleDocument::GetAbsolutePath() const
{
return m_absolutePath;
}
AZStd::string_view ShaderManagementConsoleDocument::GetRelativePath() const
{
return m_relativePath;
Clear();
}
size_t ShaderManagementConsoleDocument::GetShaderOptionCount() const
{
auto layout = m_shaderAsset->GetShaderOptionGroupLayout();
auto& shaderOptionDescriptors = layout->GetShaderOptions();
return shaderOptionDescriptors.size();
}
@@ -57,7 +41,6 @@ namespace ShaderManagementConsole
{
auto layout = m_shaderAsset->GetShaderOptionGroupLayout();
auto& shaderOptionDescriptors = layout->GetShaderOptions();
return shaderOptionDescriptors[index];
}
@@ -71,19 +54,21 @@ namespace ShaderManagementConsole
return m_shaderVariantListSourceData.m_shaderVariants[index];
}
ShaderManagementConsoleDocumentResult ShaderManagementConsoleDocument::Open(AZStd::string_view loadPath)
bool ShaderManagementConsoleDocument::Open(AZStd::string_view loadPath)
{
Clear();
m_absolutePath = loadPath;
if (!AzFramework::StringFunc::Path::Normalize(m_absolutePath))
{
return AZ::Failure(AZStd::string::format("Document path could not be normalized: '%s'.", m_absolutePath.c_str()));
AZ_Error("ShaderManagementConsoleDocument", false, "Document path could not be normalized: '%s'.", m_absolutePath.c_str());
return false;
}
if (AzFramework::StringFunc::Path::IsRelative(m_absolutePath.c_str()))
{
return AZ::Failure(AZStd::string::format("Document path must be absolute: '%s'.", m_absolutePath.c_str()));
AZ_Error("ShaderManagementConsoleDocument", false, "Document path must be absolute: '%s'.", m_absolutePath.c_str());
return false;
}
if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension))
@@ -91,7 +76,8 @@ namespace ShaderManagementConsole
// Load the shader config data and create a shader config asset from it
if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_absolutePath, m_shaderVariantListSourceData))
{
return AZ::Failure(AZStd::string::format("Failed loading shader variant list data: '%s.'", m_absolutePath.c_str()));
AZ_Error("ShaderManagementConsoleDocument", false, "Failed loading shader variant list data: '%s.'", m_absolutePath.c_str());
return false;
}
}
@@ -103,13 +89,15 @@ namespace ShaderManagementConsole
watchFolder);
if (!result)
{
return AZ::Failure(AZStd::string::format("Could not find source data: '%s'.", m_absolutePath.c_str()));
AZ_Error("ShaderManagementConsoleDocument", false, "Could not find source data: '%s'.", m_absolutePath.c_str());
return false;
}
m_relativePath = m_shaderVariantListSourceData.m_shaderFilePath;
if (!AzFramework::StringFunc::Path::Normalize(m_relativePath))
{
return AZ::Failure(AZStd::string::format("Shader path could not be normalized: '%s'.", m_relativePath.c_str()));
AZ_Error("ShaderManagementConsoleDocument", false, "Shader path could not be normalized: '%s'.", m_relativePath.c_str());
return false;
}
AZStd::string shaderPath = m_relativePath;
@@ -118,78 +106,28 @@ namespace ShaderManagementConsole
m_shaderAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath<AZ::RPI::ShaderAsset>(shaderPath.c_str());
if (!m_shaderAsset)
{
return AZ::Failure(AZStd::string::format("Could not load shader asset: %s.", shaderPath.c_str()));
AZ_Error("ShaderManagementConsoleDocument", false, "Could not load shader asset: %s.", shaderPath.c_str());
return false;
}
ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id);
return AZ::Success(AZStd::string::format("Document loaded: '%s'", m_absolutePath.c_str()));
AZ_TracePrintf("ShaderManagementConsoleDocument", "Document opened: '%s'\n", m_absolutePath.c_str());
return true;
}
ShaderManagementConsoleDocumentResult ShaderManagementConsoleDocument::Save()
bool ShaderManagementConsoleDocument::Close()
{
if (!IsOpen())
{
return AZ::Failure(AZStd::string::format("Document is not open to be saved: '%s'.", m_absolutePath.c_str()));
}
if (!IsSavable())
{
return AZ::Failure(AZStd::string::format("Document can not be saved: '%s'.", m_absolutePath.c_str()));
}
return AZ::Failure(AZStd::string::format("%s is not implemented!", __FUNCTION__));
// Auto add or checkout saved file
//AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit,
// m_absolutePath.c_str(), true,
// [](bool, const AzToolsFramework::SourceControlFileInfo&) {});
//ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentSaved, m_id);
//return AZ::Success(AZStd::string::format("Document saved: %s", m_absolutePath.data()));
}
ShaderManagementConsoleDocumentResult ShaderManagementConsoleDocument::SaveAsCopy(AZStd::string_view savePath)
{
if (!IsOpen())
{
return AZ::Failure(AZStd::string::format("Document is not open to be saved: '%s'.", m_absolutePath.c_str()));
}
if (!IsSavable())
{
return AZ::Failure(AZStd::string::format("Document can not be saved: '%s'.", m_absolutePath.c_str()));
}
AZStd::string normalizedSavePath = savePath;
if (!AzFramework::StringFunc::Path::Normalize(normalizedSavePath))
{
return AZ::Failure(AZStd::string::format("Document save path could not be normalized: '%s'.", normalizedSavePath.c_str()));
}
return AZ::Failure(AZStd::string::format("%s is not implemented!", __FUNCTION__));
// Auto add or checkout saved file
//AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit,
// normalizedSavePath.c_str(), true,
// [](bool, const AzToolsFramework::SourceControlFileInfo&) {});
//ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentSaved, m_id);
//return AZ::Success(AZStd::string::format("Document saved: %s", normalizedSavePath.c_str()));
}
ShaderManagementConsoleDocumentResult ShaderManagementConsoleDocument::Close()
{
if (!IsOpen())
{
return AZ::Failure(AZStd::string("Document is not open"));
AZ_Error("ShaderManagementConsoleDocument", false, "Document is not open");
return false;
}
Clear();
ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentClosed, m_id);
return AZ::Success(AZStd::string("Document was closed"));
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id);
AZ_TracePrintf("ShaderManagementConsoleDocument", "Document closed\n");
return true;
}
bool ShaderManagementConsoleDocument::IsOpen() const
@@ -197,77 +135,11 @@ namespace ShaderManagementConsole
return !m_absolutePath.empty() && !m_relativePath.empty();
}
bool ShaderManagementConsoleDocument::IsModified() const
{
return false;
}
bool ShaderManagementConsoleDocument::IsSavable() const
{
return true;
}
bool ShaderManagementConsoleDocument::CanUndo() const
{
// Undo will only be allowed if something has been recorded and we're not at the beginning of history
return IsOpen() && !m_undoHistory.empty() && m_undoHistoryIndex > 0;
}
bool ShaderManagementConsoleDocument::CanRedo() const
{
// Redo will only be allowed if something has been recorded and we're not at the end of history
return IsOpen() && !m_undoHistory.empty() && m_undoHistoryIndex < m_undoHistory.size();
}
bool ShaderManagementConsoleDocument::Undo()
{
if (CanUndo())
{
// The history index is one beyond the last executed command. Decrement the index then execute undo.
m_undoHistory[--m_undoHistoryIndex].first();
ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
return true;
}
return false;
}
bool ShaderManagementConsoleDocument::Redo()
{
if (CanRedo())
{
// Execute the current redo command then move the history index to the next position.
m_undoHistory[m_undoHistoryIndex++].second();
ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
return true;
}
return false;
}
bool ShaderManagementConsoleDocument::BeginEdit()
{
return true;
}
bool ShaderManagementConsoleDocument::EndEdit()
{
// Wipe any state beyond the current history index
m_undoHistory.erase(m_undoHistory.begin() + m_undoHistoryIndex, m_undoHistory.end());
// Add undo and redo operations using lambdas that will capture property state and restore it when executed
m_undoHistory.emplace_back(
[this]() { /**/ },
[this]() { /**/ });
// Assign the index to the end of history
m_undoHistoryIndex = aznumeric_cast<int>(m_undoHistory.size());
ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
return true;
}
void ShaderManagementConsoleDocument::Clear()
{
m_absolutePath.clear();
m_relativePath.clear();
m_shaderVariantListSourceData = {};
m_shaderAsset = {};
}
} // namespace ShaderManagementConsole
@@ -7,13 +7,12 @@
*/
#pragma once
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/Asset/AssetCommon.h>
#include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
#include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h>
#include <Atom/Document/ShaderManagementConsoleDocumentRequestBus.h>
#include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h>
#include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
#include <AtomToolsFramework/Document/AtomToolsDocument.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/RTTI/RTTI.h>
namespace ShaderManagementConsole
{
@@ -21,7 +20,8 @@ namespace ShaderManagementConsole
* ShaderManagementConsoleDocument provides an API for modifying and saving document properties.
*/
class ShaderManagementConsoleDocument
: public ShaderManagementConsoleDocumentRequestBus::Handler
: public AtomToolsFramework::AtomToolsDocument
, public ShaderManagementConsoleDocumentRequestBus::Handler
{
public:
AZ_RTTI(ShaderManagementConsoleDocument, "{DBA269AE-892B-415C-8FA1-166B94B0E045}");
@@ -31,29 +31,20 @@ namespace ShaderManagementConsole
ShaderManagementConsoleDocument();
virtual ~ShaderManagementConsoleDocument();
const AZ::Uuid& GetId() const;
////////////////////////////////////////////////////////////////////////
// AtomToolsFramework::AtomToolsDocument
////////////////////////////////////////////////////////////////////////
bool Open(AZStd::string_view loadPath) override;
bool Close() override;
bool IsOpen() const override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// ShaderManagementConsoleDocumentRequestBus::Handler implementation
AZStd::string_view GetAbsolutePath() const override;
AZStd::string_view GetRelativePath() const override;
size_t GetShaderOptionCount() const override;
const AZ::RPI::ShaderOptionDescriptor& GetShaderOptionDescriptor(size_t index) const override;
size_t GetShaderVariantCount() const override;
const AZ::RPI::ShaderVariantListSourceData::VariantInfo& GetShaderVariantInfo(size_t index) const override;
ShaderManagementConsoleDocumentResult Open(AZStd::string_view loadPath) override;
ShaderManagementConsoleDocumentResult Save() override;
ShaderManagementConsoleDocumentResult SaveAsCopy(AZStd::string_view savePath) override;
ShaderManagementConsoleDocumentResult Close() override;
bool IsOpen() const override;
bool IsModified() const override;
bool IsSavable() const override;
bool CanUndo() const override;
bool CanRedo() const override;
bool Undo() override;
bool Redo() override;
bool BeginEdit() override;
bool EndEdit() override;
////////////////////////////////////////////////////////////////////////
private:
@@ -67,28 +58,11 @@ namespace ShaderManagementConsole
using UndoRedoHistory = AZStd::vector<UndoRedoFunctionPair>;
void Clear();
// Unique id of this document
AZ::Uuid m_id = AZ::Uuid::CreateRandom();
// Relative path to the document
AZStd::string m_relativePath;
// Absolute path to the document
AZStd::string m_absolutePath;
// Source data for shader variant list
AZ::RPI::ShaderVariantListSourceData m_shaderVariantListSourceData;
// Shader asset for the corresponding shader variant list
AZ::Data::Asset<AZ::RPI::ShaderAsset> m_shaderAsset;
// Variables needed for tracking the undo and redo state of this document
// Container of undo commands
UndoRedoHistory m_undoHistory;
// The current position in the undo redo history
int m_undoHistoryIndex = 0;
};
} // namespace ShaderManagementConsole
@@ -7,10 +7,8 @@
*/
#include <Atom/Document/ShaderManagementConsoleDocumentModule.h>
#include <Document/ShaderManagementConsoleDocumentSystemComponent.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h>
#include <AzToolsFramework/Asset/AssetSystemComponent.h>
#include <Document/ShaderManagementConsoleDocumentSystemComponent.h>
namespace ShaderManagementConsole
{
@@ -6,39 +6,16 @@
*
*/
#include <Document/ShaderManagementConsoleDocumentSystemComponent.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzFramework/Asset/AssetSystemBus.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/API/ViewPaneOptions.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AtomToolsFramework/Util/Util.h>
#include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
#include <Atom/Document/ShaderManagementConsoleDocumentRequestBus.h>
#include <Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QApplication>
#include <QStyle>
#include <QMessageBox>
#include <QFileDialog>
AZ_POP_DISABLE_WARNING
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <Document/ShaderManagementConsoleDocument.h>
#include <Document/ShaderManagementConsoleDocumentSystemComponent.h>
namespace ShaderManagementConsole
{
ShaderManagementConsoleDocumentSystemComponent::ShaderManagementConsoleDocumentSystemComponent()
{
}
void ShaderManagementConsoleDocumentSystemComponent::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
@@ -50,7 +27,7 @@ namespace ShaderManagementConsole
{
ec->Class<ShaderManagementConsoleDocumentSystemComponent>("ShaderManagementConsoleDocumentSystemComponent", "Manages documents")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System"))
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
;
}
@@ -58,63 +35,35 @@ namespace ShaderManagementConsole
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<ShaderManagementConsoleDocumentSystemRequestBus>("ShaderManagementConsoleDocumentSystemRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole")
->Event("CreateDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CreateDocument)
->Event("DestroyDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument)
->Event("OpenDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument)
->Event("CloseDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument)
->Event("CloseAllDocuments", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocuments)
->Event("SaveDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocument)
->Event("SaveDocumentAsCopy", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocumentAsCopy)
->Event("SaveAllDocuments", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveAllDocuments)
;
behaviorContext->EBus<ShaderManagementConsoleDocumentRequestBus>("ShaderManagementConsoleDocumentRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole")
->Event("GetAbsolutePath", &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath)
->Event("GetRelativePath", &ShaderManagementConsoleDocumentRequestBus::Events::GetRelativePath)
->Event("GetShaderOptionCount", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionCount)
->Event("GetShaderOptionDescriptor", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionDescriptor)
->Event("GetShaderVariantCount", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantCount)
->Event("GetShaderVariantInfo", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantInfo)
->Event("Open", &ShaderManagementConsoleDocumentRequestBus::Events::Open)
->Event("Close", &ShaderManagementConsoleDocumentRequestBus::Events::Close)
->Event("Save", &ShaderManagementConsoleDocumentRequestBus::Events::Save)
->Event("SaveAsCopy", &ShaderManagementConsoleDocumentRequestBus::Events::SaveAsCopy)
->Event("IsOpen", &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen)
->Event("IsModified", &ShaderManagementConsoleDocumentRequestBus::Events::IsModified)
->Event("IsSavable", &ShaderManagementConsoleDocumentRequestBus::Events::IsSavable)
->Event("CanUndo", &ShaderManagementConsoleDocumentRequestBus::Events::CanUndo)
->Event("CanRedo", &ShaderManagementConsoleDocumentRequestBus::Events::CanRedo)
->Event("Undo", &ShaderManagementConsoleDocumentRequestBus::Events::Undo)
->Event("Redo", &ShaderManagementConsoleDocumentRequestBus::Events::Redo)
->Event("BeginEdit", &ShaderManagementConsoleDocumentRequestBus::Events::BeginEdit)
->Event("EndEdit", &ShaderManagementConsoleDocumentRequestBus::Events::EndEdit)
;
}
}
void ShaderManagementConsoleDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc));
required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601));
required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad));
required.push_back(AZ_CRC("RPISystem", 0xf2add773));
required.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService"));
required.push_back(AZ_CRC_CE("AssetProcessorToolsConnection"));
required.push_back(AZ_CRC_CE("AssetDatabaseService"));
required.push_back(AZ_CRC_CE("PropertyManagerService"));
required.push_back(AZ_CRC_CE("RPISystem"));
}
void ShaderManagementConsoleDocumentSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("ShaderManagementConsoleDocumentSystemService"));
provided.push_back(AZ_CRC_CE("ShaderManagementConsoleDocumentSystemService"));
}
void ShaderManagementConsoleDocumentSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC("ShaderManagementConsoleDocumentSystemService"));
incompatible.push_back(AZ_CRC_CE("ShaderManagementConsoleDocumentSystemService"));
}
void ShaderManagementConsoleDocumentSystemComponent::Init()
@@ -123,203 +72,15 @@ namespace ShaderManagementConsole
void ShaderManagementConsoleDocumentSystemComponent::Activate()
{
m_documentMap.clear();
ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType,
[]()
{
return aznew ShaderManagementConsoleDocument();
});
}
void ShaderManagementConsoleDocumentSystemComponent::Deactivate()
{
ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusDisconnect();
m_documentMap.clear();
}
AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::CreateDocument()
{
auto document = AZStd::make_unique<ShaderManagementConsoleDocument>();
if (!document)
{
AZ_Error("ShaderManagementConsoleDocument", false, "Failed to create new document");
return AZ::Uuid::CreateNull();
}
AZ::Uuid documentId = document->GetId();
m_documentMap.emplace(documentId, document.release());
return documentId;
}
bool ShaderManagementConsoleDocumentSystemComponent::DestroyDocument(const AZ::Uuid& documentId)
{
return m_documentMap.erase(documentId) != 0;
}
AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocument(AZStd::string_view path)
{
return OpenDocumentImpl(path, true);
}
bool ShaderManagementConsoleDocumentSystemComponent::CloseDocument(const AZ::Uuid& documentId)
{
bool isOpen = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isOpen, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen);
if (!isOpen)
{
return true;
}
bool isModified = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified);
if (isModified)
{
if (QMessageBox::question(QApplication::activeWindow(), "document has unsaved changes", "Would you like to close anyway?",
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
{
return false;
}
}
ShaderManagementConsoleDocumentResult closeResult = AZ::Success(AZStd::string("There is no active document"));
ShaderManagementConsoleDocumentRequestBus::EventResult(closeResult, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Close);
if (!closeResult)
{
QMessageBox::critical(QApplication::activeWindow(), "Failed to close document",
QString::fromUtf8(closeResult.GetError().data(), (int)closeResult.GetError().size()));
return false;
}
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument, documentId);
return true;
}
bool ShaderManagementConsoleDocumentSystemComponent::CloseAllDocuments()
{
bool result = true;
auto documentMap = m_documentMap;
for (const auto& documentPair : documentMap)
{
if (!CloseDocument(documentPair.first))
{
result = false;
}
}
return result;
}
bool ShaderManagementConsoleDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId)
{
AZStd::string documentPath;
ShaderManagementConsoleDocumentRequestBus::EventResult(documentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath);
const QFileInfo saveInfo(documentPath.c_str());
if (saveInfo.absoluteFilePath().isEmpty())
{
return false;
}
if (saveInfo.exists() && !saveInfo.isWritable())
{
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Unable to save document. File can not be overwritten."));
return false;
}
ShaderManagementConsoleDocumentResult result = AZ::Failure(AZStd::string("There is no active document"));
ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Save);
if (!result)
{
QMessageBox::critical(QApplication::activeWindow(), "document not saved",
QString::fromUtf8(result.GetError().data(), (int)result.GetError().size()));
return false;
}
AZ_TracePrintf("ShaderManagementConsole", "%s\n", result.GetValue().c_str());
return true;
}
bool ShaderManagementConsoleDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId)
{
AZStd::string documentPath;
ShaderManagementConsoleDocumentRequestBus::EventResult(documentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath);
const QFileInfo& saveInfo = AtomToolsFramework::GetSaveFileInfo(documentPath.c_str());
if (saveInfo.absoluteFilePath().isEmpty())
{
return false;
}
AZStd::string saveDocumentPath = saveInfo.absoluteFilePath().toUtf8().constData();
AzFramework::StringFunc::Path::Normalize(saveDocumentPath);
ShaderManagementConsoleDocumentResult result = AZ::Failure(AZStd::string("There is no active document"));
ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath);
if (!result)
{
QMessageBox::critical(QApplication::activeWindow(), "document copy not saved",
QString::fromUtf8(result.GetError().data(), (int)result.GetError().size()));
return false;
}
AZ_TracePrintf("ShaderManagementConsole", "%s\n", result.GetValue().c_str());
return true;
}
bool ShaderManagementConsoleDocumentSystemComponent::SaveAllDocuments()
{
bool result = true;
for (const auto& documentPair : m_documentMap)
{
if (!SaveDocument(documentPair.first))
{
result = false;
}
}
return result;
}
AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view path, bool checkIfAlreadyOpen)
{
AZStd::string requestedPath = path;
if (requestedPath.empty() || !AzFramework::StringFunc::Path::Normalize(requestedPath))
{
QMessageBox::critical(QApplication::activeWindow(), "document path is invalid",
QString::fromUtf8(requestedPath.data(), (int)requestedPath.size()));
return AZ::Uuid::CreateNull();
}
// Determine if the file is already open and select it
if (checkIfAlreadyOpen)
{
for (const auto& documentPair : m_documentMap)
{
AZStd::string openDocumentPath;
ShaderManagementConsoleDocumentRequestBus::EventResult(openDocumentPath, documentPair.first, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath);
if (openDocumentPath == requestedPath)
{
ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first);
return documentPair.first;
}
}
}
AZ::Uuid documentId = AZ::Uuid::CreateNull();
ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(documentId, &ShaderManagementConsoleDocumentSystemRequestBus::Events::CreateDocument);
if (documentId.IsNull())
{
QMessageBox::critical(QApplication::activeWindow(), "Failed to create document",
QString::fromUtf8(requestedPath.data(), (int)requestedPath.size()));
return AZ::Uuid::CreateNull();
}
ShaderManagementConsoleDocumentResult openResult = AZ::Failure(AZStd::string("Failed to open document"));
ShaderManagementConsoleDocumentRequestBus::EventResult(openResult, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Open, requestedPath);
if (!openResult)
{
QMessageBox::critical(QApplication::activeWindow(), "Failed to open document",
QString::fromUtf8(openResult.GetError().data(), (int)openResult.GetError().size()));
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument, documentId);
return AZ::Uuid::CreateNull();
}
return documentId;
}
}
@@ -9,28 +9,17 @@
#pragma once
#include <AzCore/Component/Component.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
#include <Atom/RPI.Public/WindowContext.h>
#include <Document/ShaderManagementConsoleDocument.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QFileInfo>
#include <QString>
AZ_POP_DISABLE_WARNING
namespace ShaderManagementConsole
{
//! ShaderManagementConsoleDocumentSystemComponent is the central component of the Shader Management Console Core gem
//! ShaderManagementConsoleDocumentSystemComponent
class ShaderManagementConsoleDocumentSystemComponent
: public AZ::Component
, private ShaderManagementConsoleDocumentSystemRequestBus::Handler
{
public:
AZ_COMPONENT(ShaderManagementConsoleDocumentSystemComponent, "{58ABE0AE-2710-41E2-ADFD-E2D67407427D}");
AZ_COMPONENT(ShaderManagementConsoleDocumentSystemComponent, "{1610159D-59DC-48B1-B2D1-FCE7AFD3B012}");
ShaderManagementConsoleDocumentSystemComponent();
ShaderManagementConsoleDocumentSystemComponent() = default;
~ShaderManagementConsoleDocumentSystemComponent() = default;
ShaderManagementConsoleDocumentSystemComponent(const ShaderManagementConsoleDocumentSystemComponent&) = delete;
ShaderManagementConsoleDocumentSystemComponent& operator =(const ShaderManagementConsoleDocumentSystemComponent&) = delete;
@@ -48,21 +37,5 @@ namespace ShaderManagementConsole
void Activate() override;
void Deactivate() override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// ShaderManagementConsoleDocumentSystemRequestBus::Handler overrides...
AZ::Uuid CreateDocument() override;
bool DestroyDocument(const AZ::Uuid& documentId) override;
AZ::Uuid OpenDocument(AZStd::string_view path) override;
bool CloseDocument(const AZ::Uuid& documentId) override;
bool CloseAllDocuments() override;
bool SaveDocument(const AZ::Uuid& documentId) override;
bool SaveDocumentAsCopy(const AZ::Uuid& documentId) override;
bool SaveAllDocuments() override;
////////////////////////////////////////////////////////////////////////
AZ::Uuid OpenDocumentImpl(AZStd::string_view path, bool checkIfAlreadyOpen);
AZStd::unordered_map<AZ::Uuid, AZStd::shared_ptr<ShaderManagementConsoleDocument>> m_documentMap;
};
}
@@ -7,8 +7,8 @@
*/
#include <Atom/Document/ShaderManagementConsoleDocumentModule.h>
#include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
#include <Atom/Window/ShaderManagementConsoleWindowModule.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <ShaderManagementConsoleApplication.h>
#include <ShaderManagementConsole_Traits_Platform.h>
@@ -66,8 +66,8 @@ namespace ShaderManagementConsole
const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex);
AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str());
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(
&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
}
Base::ProcessCommandLine(commandLine);
@@ -8,8 +8,8 @@
#pragma once
#include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Application/AtomToolsApplication.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
namespace ShaderManagementConsole
{
@@ -6,28 +6,24 @@
*
*/
#include <QApplication>
#include <QMenu>
#include <QInputDialog>
#include <QMessageBox>
#include <QFileDialog>
#include <QDesktopServices>
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/Thumbnails/SourceControlThumbnail.h>
#include <AtomToolsFramework/Util/Util.h>
#include <Window/ShaderManagementConsoleBrowserInteractions.h>
#include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h>
#include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
#include <Source/Window/ShaderManagementConsoleBrowserInteractions.h>
#include <QApplication>
#include <QDesktopServices>
#include <QFileDialog>
#include <QInputDialog>
#include <QMenu>
#include <QMessageBox>
namespace ShaderManagementConsole
{
@@ -80,7 +76,7 @@ namespace ShaderManagementConsole
{
if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::ShaderVariantListSourceData::Extension))
{
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath().c_str());
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath().c_str());
}
else
{
@@ -6,26 +6,21 @@
*
*/
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h>
#include <AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
#include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
#include <Atom/Document/ShaderManagementConsoleDocumentRequestBus.h>
#include <Source/Window/ShaderManagementConsoleBrowserWidget.h>
#include <Source/Window/ui_ShaderManagementConsoleBrowserWidget.h>
#include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
#include <AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h>
#include <Window/ShaderManagementConsoleBrowserWidget.h>
#include <Window/ui_ShaderManagementConsoleBrowserWidget.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QDesktopServices>
@@ -85,14 +80,14 @@ namespace ShaderManagementConsole
});
AssetBrowserModelNotificationBus::Handler::BusConnect();
ShaderManagementConsoleDocumentNotificationBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect();
}
ShaderManagementConsoleBrowserWidget::~ShaderManagementConsoleBrowserWidget()
{
// Maintains the tree expansion state between runs
m_ui->m_assetBrowserTreeViewWidget->SaveState();
ShaderManagementConsoleDocumentNotificationBus::Handler::BusDisconnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
AssetBrowserModelNotificationBus::Handler::BusDisconnect();
}
@@ -150,7 +145,7 @@ namespace ShaderManagementConsole
{
if (AzFramework::StringFunc::Path::IsExtension(sourceEntry->GetFullPath().c_str(), AZ::RPI::ShaderVariantListSourceData::Extension))
{
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, sourceEntry->GetFullPath());
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, sourceEntry->GetFullPath());
}
else
{
@@ -192,7 +187,7 @@ namespace ShaderManagementConsole
void ShaderManagementConsoleBrowserWidget::OnDocumentOpened(const AZ::Uuid& documentId)
{
AZStd::string absolutePath;
ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (!absolutePath.empty())
{
m_pathToSelect = absolutePath;
@@ -203,4 +198,4 @@ namespace ShaderManagementConsole
} // namespace ShaderManagementConsole
#include <Source/Window/moc_ShaderManagementConsoleBrowserWidget.cpp>
#include <Window/moc_ShaderManagementConsoleBrowserWidget.cpp>
@@ -9,11 +9,10 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
#include <AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
#include <Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QWidget>
@@ -44,7 +43,7 @@ namespace ShaderManagementConsole
class ShaderManagementConsoleBrowserWidget
: public QWidget
, public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler
, public ShaderManagementConsoleDocumentNotificationBus::Handler
, public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
{
Q_OBJECT
public:
@@ -64,7 +63,7 @@ namespace ShaderManagementConsole
// AssetBrowserModelNotificationBus::Handler implementation
void EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) override;
// ShaderManagementConsoleDocumentNotificationBus::Handler implementation
// AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler implementation
void OnDocumentOpened(const AZ::Uuid& documentId) override;
};
} // namespace ShaderManagementConsole
@@ -13,12 +13,11 @@
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h>
#include <Atom/Document/ShaderManagementConsoleDocumentRequestBus.h>
#include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <Window/ShaderManagementConsoleWindow.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
@@ -62,19 +61,19 @@ namespace ShaderManagementConsole
// Restore geometry and show the window
mainWindowWrapper->showFromSettings();
ShaderManagementConsoleDocumentNotificationBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect();
OnDocumentOpened(AZ::Uuid::CreateNull());
}
ShaderManagementConsoleWindow::~ShaderManagementConsoleWindow()
{
ShaderManagementConsoleDocumentNotificationBus::Handler::BusDisconnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
}
void ShaderManagementConsoleWindow::closeEvent(QCloseEvent* closeEvent)
{
bool didClose = true;
ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(didClose, &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocuments);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(didClose, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
if (!didClose)
{
closeEvent->ignore();
@@ -88,17 +87,17 @@ namespace ShaderManagementConsole
void ShaderManagementConsoleWindow::OnDocumentOpened(const AZ::Uuid& documentId)
{
bool isOpen = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isOpen, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsOpen);
bool isSavable = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isSavable, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsSavable);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isSavable, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsSavable);
bool isModified = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified);
bool canUndo = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(canUndo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanUndo);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo);
bool canRedo = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(canRedo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanRedo);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo);
AZStd::string absolutePath;
ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
@@ -150,7 +149,7 @@ namespace ShaderManagementConsole
const QString documentPath = GetDocumentPath(documentId);
if (!documentPath.isEmpty())
{
const QString status = QString("Document closed: %1").arg(documentPath);
const QString status = QString("Document opened: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"White\">%1</font>").arg(status));
}
}
@@ -167,9 +166,9 @@ namespace ShaderManagementConsole
void ShaderManagementConsoleWindow::OnDocumentModified(const AZ::Uuid& documentId)
{
bool isModified = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified);
AZStd::string absolutePath;
ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
@@ -180,9 +179,9 @@ namespace ShaderManagementConsole
if (documentId == GetDocumentIdFromTab(m_tabWidget->currentIndex()))
{
bool canUndo = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(canUndo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanUndo);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo);
bool canRedo = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(canRedo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanRedo);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo);
m_actionUndo->setEnabled(canUndo);
m_actionRedo->setEnabled(canRedo);
}
@@ -191,15 +190,15 @@ namespace ShaderManagementConsole
void ShaderManagementConsoleWindow::OnDocumentSaved(const AZ::Uuid& documentId)
{
bool isModified = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified);
AZStd::string absolutePath;
ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
const QString documentPath = GetDocumentPath(documentId);
const QString status = QString("Document closed: %1").arg(documentPath);
const QString status = QString("Document saved: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"White\">%1</font>").arg(status));
}
@@ -217,7 +216,7 @@ namespace ShaderManagementConsole
const AZStd::string filePath = AtomToolsFramework::GetOpenFileInfo(assetTypes).absoluteFilePath().toUtf8().constData();
if (!filePath.empty())
{
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, filePath);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, filePath);
}
}, QKeySequence::Open);
@@ -225,32 +224,56 @@ namespace ShaderManagementConsole
m_menuFile->addSeparator();
m_actionClose = m_menuFile->addAction("&Close", [this]() {
CloseDocumentForTab(m_tabWidget->currentIndex());
}, QKeySequence::Close);
m_actionCloseAll = m_menuFile->addAction("Close All", [this]() {
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocuments);
});
m_actionCloseOthers = m_menuFile->addAction("Close Others", [this]() {
CloseAllExceptDocumentForTab(m_tabWidget->currentIndex());
});
m_menuFile->addSeparator();
m_actionSave = m_menuFile->addAction("&Save", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocument, documentId);
bool result = false;
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId);
if (!result)
{
const QString documentPath = GetDocumentPath(documentId);
const QString status = QString("Document save failed: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(status));
}
}, QKeySequence::Save);
m_actionSaveAsCopy = m_menuFile->addAction("Save &As...", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocumentAsCopy, documentId);
const QString documentPath = GetDocumentPath(documentId);
bool result = false;
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy,
documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
if (!result)
{
const QString status = QString("Document save failed: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(status));
}
}, QKeySequence::SaveAs);
m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() {
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveAllDocuments);
bool result = false;
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments);
if (!result)
{
const QString status = QString("Document save all failed.");
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(status));
}
});
m_menuFile->addSeparator();
m_actionClose = m_menuFile->addAction("&Close", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
}, QKeySequence::Close);
m_actionCloseAll = m_menuFile->addAction("Close All", [this]() {
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
});
m_actionCloseOthers = m_menuFile->addAction("Close Others", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
});
m_menuFile->addSeparator();
@@ -274,11 +297,11 @@ namespace ShaderManagementConsole
m_actionUndo = m_menuEdit->addAction("&Undo", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
bool result = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Undo);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Undo);
if (!result)
{
const QString documentPath = GetDocumentPath(documentId);
const QString status = QString("Failed to perform undo on document: %1").arg(documentPath);
const QString status = QString("Document undo failed: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(status));
}
}, QKeySequence::Undo);
@@ -286,30 +309,27 @@ namespace ShaderManagementConsole
m_actionRedo = m_menuEdit->addAction("&Redo", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
bool result = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Redo);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Redo);
if (!result)
{
const QString documentPath = GetDocumentPath(documentId);
const QString status = QString("Failed to perform redo on document: %1").arg(documentPath);
const QString status = QString("Document redo failed: %1").arg(documentPath);
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(status));
}
}, QKeySequence::Redo);
m_menuEdit->addSeparator();
m_actionSettings = m_menuEdit->addAction("&Preferences...", [this]() {
m_actionSettings = m_menuEdit->addAction("&Settings...", [this]() {
}, QKeySequence::Preferences);
m_actionSettings->setEnabled(false);
m_menuView = m_menuBar->addMenu("&View");
m_actionAssetBrowser = m_menuView->addAction(
"&Asset Browser",
[this]()
{
const AZStd::string label = "Asset Browser";
SetDockWidgetVisible(label, !IsDockWidgetVisible(label));
});
m_actionAssetBrowser = m_menuView->addAction("&Asset Browser", [this]() {
const AZStd::string label = "Asset Browser";
SetDockWidgetVisible(label, !IsDockWidgetVisible(label));
});
m_actionPythonTerminal = m_menuView->addAction("Python &Terminal", [this]() {
const AZStd::string label = "Python Terminal";
@@ -344,18 +364,20 @@ namespace ShaderManagementConsole
// When the last tab is removed tabIndex will be -1 and the document ID will be null
// This should automatically clear the active document
connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) {
SelectDocumentForTab(tabIndex);
const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
});
connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) {
CloseDocumentForTab(tabIndex);
const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
});
}
QString ShaderManagementConsoleWindow::GetDocumentPath(const AZ::Uuid& documentId) const
{
AZStd::string absolutePath;
ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Handler::GetAbsolutePath);
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Handler::GetAbsolutePath);
return absolutePath.c_str();
}
@@ -370,51 +392,22 @@ namespace ShaderManagementConsole
QMenu tabMenu;
const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select";
tabMenu.addAction(selectActionName, [this, clickedTabIndex]() {
SelectDocumentForTab(clickedTabIndex);
const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
});
tabMenu.addAction("Close", [this, clickedTabIndex]() {
CloseDocumentForTab(clickedTabIndex);
const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
});
auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() {
CloseAllExceptDocumentForTab(clickedTabIndex);
const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
});
closeOthersAction->setEnabled(tabBar->count() > 1);
tabMenu.exec(QCursor::pos());
}
}
void ShaderManagementConsoleWindow::SelectDocumentForTab(const int tabIndex)
{
const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentId);
}
void ShaderManagementConsoleWindow::CloseDocumentForTab(const int tabIndex)
{
const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId);
}
void ShaderManagementConsoleWindow::CloseAllExceptDocumentForTab(const int tabIndex)
{
AZStd::vector<AZ::Uuid> documentIdsToClose;
documentIdsToClose.reserve(m_tabWidget->count());
const AZ::Uuid documentIdToKeepOpen = GetDocumentIdFromTab(tabIndex);
for (int tabI = 0; tabI < m_tabWidget->count(); ++tabI)
{
const AZ::Uuid documentId = GetDocumentIdFromTab(tabI);
if (documentId != documentIdToKeepOpen)
{
documentIdsToClose.push_back(documentId);
}
}
for (const AZ::Uuid& documentId : documentIdsToClose)
{
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId);
}
}
QStandardItemModel* ShaderManagementConsoleWindow::CreateDocumentContent(const AZ::Uuid& documentId)
{
AZStd::unordered_set<AZStd::string> optionNames;
@@ -9,9 +9,9 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h>
#include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h>
#include <Atom/RPI.Public/Shader/Shader.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindow.h>
#include <AzCore/Memory/SystemAllocator.h>
@@ -31,7 +31,7 @@ namespace ShaderManagementConsole
*/
class ShaderManagementConsoleWindow
: public AtomToolsFramework::AtomToolsMainWindow
, private ShaderManagementConsoleDocumentNotificationBus::Handler
, private AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
{
Q_OBJECT
public:
@@ -43,7 +43,7 @@ namespace ShaderManagementConsole
~ShaderManagementConsoleWindow();
private:
// ShaderManagementConsoleDocumentNotificationBus::Handler overrides...
// AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler overrides...
void OnDocumentOpened(const AZ::Uuid& documentId) override;
void OnDocumentClosed(const AZ::Uuid& documentId) override;
void OnDocumentModified(const AZ::Uuid& documentId) override;
@@ -57,10 +57,6 @@ namespace ShaderManagementConsole
void OpenTabContextMenu() override;
void SelectDocumentForTab(const int tabIndex);
void CloseDocumentForTab(const int tabIndex);
void CloseAllExceptDocumentForTab(const int tabIndex);
void closeEvent(QCloseEvent* closeEvent) override;
QStandardItemModel* CreateDocumentContent(const AZ::Uuid& documentId);
@@ -6,25 +6,20 @@
*
*/
#include <Atom/RPI.Edit/Common/JsonUtils.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Public/Material/Material.h>
#include <AssetDatabase/AssetDatabaseConnection.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Common/JsonUtils.h>
#include <Atom/RPI.Public/Material/Material.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/UI/UICore/QWidgetSavedState.h>
#include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
#include <Source/Window/ShaderManagementConsoleWindowComponent.h>
#include <Source/Window/ShaderManagementConsoleWindow.h>
#include <Window/ShaderManagementConsoleWindow.h>
#include <Window/ShaderManagementConsoleWindowComponent.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QFile>
@@ -10,7 +10,5 @@ set(FILES
Source/main.cpp
Source/ShaderManagementConsoleApplication.cpp
Source/ShaderManagementConsoleApplication.h
Include/Atom/Document/ShaderManagementConsoleDocumentModule.h
Source/Document/ShaderManagementConsoleDocumentModule.cpp
../Scripts/GenerateShaderVariantListForMaterials.py
)
@@ -7,11 +7,11 @@
#
set(FILES
Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h
Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h
Include/Atom/Document/ShaderManagementConsoleDocumentModule.h
Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h
Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp
Source/Document/ShaderManagementConsoleDocumentSystemComponent.h
Source/Document/ShaderManagementConsoleDocument.cpp
Source/Document/ShaderManagementConsoleDocument.h
Source/Document/ShaderManagementConsoleDocumentModule.cpp
Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp
Source/Document/ShaderManagementConsoleDocumentSystemComponent.h
)
@@ -153,7 +153,7 @@ def main():
azlmbr.shader.SaveShaderVariantListSourceData(shaderVariantListFilePath, shaderVariantList)
# Open the document in shader management console
result = azlmbr.shadermanagementconsole.ShaderManagementConsoleDocumentSystemRequestBus(
result = azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(
azlmbr.bus.Broadcast,
'OpenDocument',
shaderVariantListFilePath