Atom Tools: Saving tool settings, made inspector configurable, moved to ATF
Changed material editor inspector into generic, configurable, document inspector and moved to atom tools framework Renamed atom tools framework settings registry utility functions Added more settings registry utility functions to get, set, and save values and objects Added saving tool settings to atom tools application Signed-off-by: Guthrie Adams <guthadam@amazon.com>development
parent
c0299f0ad7
commit
01786b2966
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
|
||||
#include <AtomToolsFramework/Inspector/InspectorWidget.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h>
|
||||
#endif
|
||||
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
//! This is a specialized inspector widget that populates itself by inspecting document reflected object info.
|
||||
//! Each element of an AtomToolsDocument object info vector will be displayed in a collapsible RPE group in the inspector.
|
||||
//! Property changes emitted from each RPE will be tracked and used to signal undo/redo events in the document.
|
||||
class AtomToolsDocumentInspector
|
||||
: public InspectorWidget
|
||||
, public AtomToolsDocumentNotificationBus::Handler
|
||||
, public AzToolsFramework::IPropertyEditorNotify
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AtomToolsDocumentInspector, AZ::SystemAllocator, 0);
|
||||
|
||||
AtomToolsDocumentInspector(const AZ::Crc32& toolId, QWidget* parent = nullptr);
|
||||
~AtomToolsDocumentInspector() override;
|
||||
|
||||
//! Set the ID of the document that will be used to populate the inspector
|
||||
void SetDocumentId(const AZ::Uuid& documentId);
|
||||
|
||||
//! Set a prefix string for storing registry settings
|
||||
void SetDocumentSettingsPrefix(const AZStd::string& prefix);
|
||||
|
||||
using NodeIndicatorFunction = AZStd::function<const char*(const AzToolsFramework::InstanceDataNode*)>;
|
||||
|
||||
//! Set a function that will be used to determine what, if any, icon should be displayed next to a property in the inspector
|
||||
void SetIndicatorFunction(const NodeIndicatorFunction& indicatorFunction);
|
||||
|
||||
// InspectorRequestBus::Handler overrides...
|
||||
void Reset() override;
|
||||
|
||||
private:
|
||||
// AtomToolsDocumentNotificationBus::Handler implementation
|
||||
void OnDocumentObjectInfoChanged(const AZ::Uuid& documentId, const DocumentObjectInfo& objectInfo, bool rebuilt) override;
|
||||
|
||||
// AzToolsFramework::IPropertyEditorNotify overrides...
|
||||
void BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode) override;
|
||||
void AfterPropertyModified([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode) override {}
|
||||
void SetPropertyEditingActive([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode) override {}
|
||||
void SetPropertyEditingComplete(AzToolsFramework::InstanceDataNode* pNode) override;
|
||||
void SealUndoStack() override {}
|
||||
void RequestPropertyContextMenu([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode, const QPoint&) override {}
|
||||
void PropertySelectionChanged([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode, bool) override {}
|
||||
|
||||
const AZ::Crc32 m_toolId = {};
|
||||
|
||||
bool m_editInProgress = {};
|
||||
|
||||
AZ::Uuid m_documentId = AZ::Uuid::CreateNull();
|
||||
|
||||
NodeIndicatorFunction m_nodeIndicatorFunction;
|
||||
|
||||
AZStd::string m_documentSettingsPrefix = "/O3DE/AtomToolsFramework/AtomToolsDocumentInspector";
|
||||
};
|
||||
} // namespace AtomToolsFramework
|
||||
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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/AtomToolsDocumentInspector.h>
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
|
||||
#include <AtomToolsFramework/Inspector/InspectorPropertyGroupWidget.h>
|
||||
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
AtomToolsDocumentInspector::AtomToolsDocumentInspector(const AZ::Crc32& toolId, QWidget* parent)
|
||||
: InspectorWidget(parent)
|
||||
, m_toolId(toolId)
|
||||
{
|
||||
AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
|
||||
}
|
||||
|
||||
AtomToolsDocumentInspector::~AtomToolsDocumentInspector()
|
||||
{
|
||||
AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void AtomToolsDocumentInspector::SetDocumentId(const AZ::Uuid& documentId)
|
||||
{
|
||||
AddGroupsBegin();
|
||||
|
||||
m_documentId = documentId;
|
||||
|
||||
AtomToolsDocumentRequestBus::Event(
|
||||
m_documentId,
|
||||
[&](AtomToolsDocumentRequests* documentRequests)
|
||||
{
|
||||
if (documentRequests->IsOpen())
|
||||
{
|
||||
// Create a unique settings prefix string per document using a CRC of the document path
|
||||
const AZStd::string groupSettingsPrefix = m_documentSettingsPrefix +
|
||||
AZStd::string::format("/%08x/GroupSettings", aznumeric_cast<AZ::u32>(AZ::Crc32(documentRequests->GetAbsolutePath())));
|
||||
SetGroupSettingsPrefix(groupSettingsPrefix);
|
||||
|
||||
// This will automatically expose all document contents to an inspector with a collapsible group per object.
|
||||
// In the case of the material editor, this will be one inspector group per property group.
|
||||
for (auto& objectInfo : documentRequests->GetObjectInfo())
|
||||
{
|
||||
// Passing in same main and comparison instance to enable custom value comparison
|
||||
const AZ::Crc32 groupSaveStateKey(
|
||||
AZStd::string::format("%s/%s", groupSettingsPrefix.c_str(), objectInfo.m_name.c_str()));
|
||||
auto propertyGroupWidget = new InspectorPropertyGroupWidget(
|
||||
objectInfo.m_objectPtr, objectInfo.m_objectPtr, objectInfo.m_objectType, this, this, groupSaveStateKey, {},
|
||||
m_nodeIndicatorFunction, 0);
|
||||
|
||||
AddGroup(objectInfo.m_name, objectInfo.m_displayName, objectInfo.m_description, propertyGroupWidget);
|
||||
SetGroupVisible(objectInfo.m_name, objectInfo.m_visible);
|
||||
}
|
||||
}
|
||||
|
||||
InspectorRequestBus::Handler::BusConnect(m_documentId);
|
||||
});
|
||||
|
||||
AddGroupsEnd();
|
||||
}
|
||||
|
||||
void AtomToolsDocumentInspector::SetDocumentSettingsPrefix(const AZStd::string& prefix)
|
||||
{
|
||||
m_documentSettingsPrefix = prefix;
|
||||
}
|
||||
|
||||
void AtomToolsDocumentInspector::SetIndicatorFunction(const NodeIndicatorFunction& indicatorFunction)
|
||||
{
|
||||
m_nodeIndicatorFunction = indicatorFunction;
|
||||
}
|
||||
|
||||
void AtomToolsDocumentInspector::Reset()
|
||||
{
|
||||
m_documentId = AZ::Uuid::CreateNull();
|
||||
m_editInProgress = false;
|
||||
|
||||
InspectorWidget::Reset();
|
||||
}
|
||||
|
||||
void AtomToolsDocumentInspector::OnDocumentObjectInfoChanged(
|
||||
[[maybe_unused]] const AZ::Uuid& documentId, const DocumentObjectInfo& objectInfo, bool rebuilt)
|
||||
{
|
||||
if (m_documentId == documentId)
|
||||
{
|
||||
SetGroupVisible(objectInfo.m_name, objectInfo.m_visible);
|
||||
if (rebuilt)
|
||||
{
|
||||
RebuildGroup(objectInfo.m_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
RefreshGroup(objectInfo.m_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AtomToolsDocumentInspector::BeforePropertyModified([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode)
|
||||
{
|
||||
if (!m_editInProgress)
|
||||
{
|
||||
m_editInProgress = true;
|
||||
AtomToolsDocumentRequestBus::Event(m_documentId, &AtomToolsDocumentRequestBus::Events::BeginEdit);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomToolsDocumentInspector::SetPropertyEditingComplete([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode)
|
||||
{
|
||||
if (m_editInProgress)
|
||||
{
|
||||
m_editInProgress = false;
|
||||
AtomToolsDocumentRequestBus::Event(m_documentId, &AtomToolsDocumentRequestBus::Events::EndEdit);
|
||||
}
|
||||
}
|
||||
} // namespace AtomToolsFramework
|
||||
|
||||
//#include <AtomToolsFramework/Document/moc_AtomToolsDocumentInspector.cpp>
|
||||
@ -1,159 +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
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/RPI.Edit/Common/AssetUtils.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
|
||||
{
|
||||
MaterialInspector::MaterialInspector(const AZ::Crc32& toolId, QWidget* parent)
|
||||
: AtomToolsFramework::InspectorWidget(parent)
|
||||
, m_toolId(toolId)
|
||||
{
|
||||
m_windowSettings = AZ::UserSettings::CreateFind<MaterialEditorWindowSettings>(
|
||||
AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL);
|
||||
|
||||
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
|
||||
}
|
||||
|
||||
MaterialInspector::~MaterialInspector()
|
||||
{
|
||||
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
|
||||
AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void MaterialInspector::Reset()
|
||||
{
|
||||
m_documentPath.clear();
|
||||
m_documentId = AZ::Uuid::CreateNull();
|
||||
m_activeProperty = {};
|
||||
|
||||
AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect();
|
||||
AtomToolsFramework::InspectorWidget::Reset();
|
||||
}
|
||||
|
||||
bool MaterialInspector::ShouldGroupAutoExpanded(const AZStd::string& groupName) const
|
||||
{
|
||||
auto stateItr = m_windowSettings->m_inspectorCollapsedGroups.find(GetGroupSaveStateKey(groupName));
|
||||
return stateItr == m_windowSettings->m_inspectorCollapsedGroups.end();
|
||||
}
|
||||
|
||||
void MaterialInspector::OnGroupExpanded(const AZStd::string& groupName)
|
||||
{
|
||||
m_windowSettings->m_inspectorCollapsedGroups.erase(GetGroupSaveStateKey(groupName));
|
||||
}
|
||||
|
||||
void MaterialInspector::OnGroupCollapsed(const AZStd::string& groupName)
|
||||
{
|
||||
m_windowSettings->m_inspectorCollapsedGroups.insert(GetGroupSaveStateKey(groupName));
|
||||
}
|
||||
|
||||
void MaterialInspector::OnDocumentOpened(const AZ::Uuid& documentId)
|
||||
{
|
||||
AddGroupsBegin();
|
||||
|
||||
m_documentId = documentId;
|
||||
|
||||
bool isOpen = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
|
||||
isOpen, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsOpen);
|
||||
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
|
||||
m_documentPath, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
|
||||
|
||||
if (!m_documentId.IsNull() && isOpen)
|
||||
{
|
||||
// This will automatically expose all document contents to an inspector with a collapsible group per object. In the case of the
|
||||
// material editor, this will be one inspector group per property group.
|
||||
AZStd::vector<AtomToolsFramework::DocumentObjectInfo> objects;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
|
||||
objects, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetObjectInfo);
|
||||
|
||||
for (auto& objectInfo : objects)
|
||||
{
|
||||
// Passing in same main and comparison instance to enable custom value comparison for highlighting modified properties
|
||||
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
|
||||
objectInfo.m_objectPtr, objectInfo.m_objectPtr, objectInfo.m_objectType, this, this,
|
||||
GetGroupSaveStateKey(objectInfo.m_name), {},
|
||||
[this](const auto node) { return GetInstanceNodePropertyIndicator(node); }, 0);
|
||||
|
||||
AddGroup(objectInfo.m_name, objectInfo.m_displayName, objectInfo.m_description, propertyGroupWidget);
|
||||
SetGroupVisible(objectInfo.m_name, objectInfo.m_visible);
|
||||
}
|
||||
|
||||
AtomToolsFramework::InspectorRequestBus::Handler::BusConnect(m_documentId);
|
||||
}
|
||||
|
||||
AddGroupsEnd();
|
||||
}
|
||||
|
||||
AZ::Crc32 MaterialInspector::GetGroupSaveStateKey(const AZStd::string& groupName) const
|
||||
{
|
||||
return AZ::Crc32(AZStd::string::format("MaterialInspector::PropertyGroup::%s::%s", m_documentPath.c_str(), groupName.c_str()));
|
||||
}
|
||||
|
||||
bool MaterialInspector::IsInstanceNodePropertyModifed(const AzToolsFramework::InstanceDataNode* node) const
|
||||
{
|
||||
const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(node);
|
||||
return property && !AtomToolsFramework::ArePropertyValuesEqual(property->GetValue(), property->GetConfig().m_parentValue);
|
||||
}
|
||||
|
||||
const char* MaterialInspector::GetInstanceNodePropertyIndicator(const AzToolsFramework::InstanceDataNode* node) const
|
||||
{
|
||||
if (IsInstanceNodePropertyModifed(node))
|
||||
{
|
||||
return ":/Icons/changed_property.svg";
|
||||
}
|
||||
return ":/Icons/blank.png";
|
||||
}
|
||||
|
||||
void MaterialInspector::OnDocumentObjectInfoChanged(
|
||||
[[maybe_unused]] const AZ::Uuid& documentId, const AtomToolsFramework::DocumentObjectInfo& objectInfo, bool rebuilt)
|
||||
{
|
||||
SetGroupVisible(objectInfo.m_name, objectInfo.m_visible);
|
||||
if (rebuilt)
|
||||
{
|
||||
RebuildGroup(objectInfo.m_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
RefreshGroup(objectInfo.m_name);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialInspector::BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode)
|
||||
{
|
||||
// This function is called before every single property change whether it's a button click or dragging a slider. We only want to
|
||||
// begin tracking undo state for the first change in the sequence, when the user begins to drag the slider.
|
||||
const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(pNode);
|
||||
if (!m_activeProperty && property)
|
||||
{
|
||||
m_activeProperty = property;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::Event(
|
||||
m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::BeginEdit);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialInspector::SetPropertyEditingComplete(AzToolsFramework::InstanceDataNode* pNode)
|
||||
{
|
||||
// If tracking has started and editing has completed then we can stop tracking undue state for this sequence of changes.
|
||||
const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(pNode);
|
||||
if (m_activeProperty && m_activeProperty == property)
|
||||
{
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::Event(
|
||||
m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::EndEdit);
|
||||
m_activeProperty = {};
|
||||
}
|
||||
}
|
||||
} // namespace MaterialEditor
|
||||
|
||||
#include <Window/MaterialInspector/moc_MaterialInspector.cpp>
|
||||
@ -1,71 +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
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
|
||||
#include <AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h>
|
||||
#include <AtomToolsFramework/Inspector/InspectorWidget.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h>
|
||||
#include <Window/MaterialEditorWindowSettings.h>
|
||||
#endif
|
||||
|
||||
namespace MaterialEditor
|
||||
{
|
||||
//! Provides controls for viewing and editing document settings.
|
||||
class MaterialInspector
|
||||
: public AtomToolsFramework::InspectorWidget
|
||||
, public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
|
||||
, public AzToolsFramework::IPropertyEditorNotify
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialInspector, AZ::SystemAllocator, 0);
|
||||
|
||||
MaterialInspector(const AZ::Crc32& toolId, QWidget* parent = nullptr);
|
||||
~MaterialInspector() override;
|
||||
|
||||
// AtomToolsFramework::InspectorRequestBus::Handler overrides...
|
||||
void Reset() override;
|
||||
|
||||
protected:
|
||||
bool ShouldGroupAutoExpanded(const AZStd::string& groupName) const override;
|
||||
void OnGroupExpanded(const AZStd::string& groupName) override;
|
||||
void OnGroupCollapsed(const AZStd::string& groupName) override;
|
||||
|
||||
private:
|
||||
AZ::Crc32 GetGroupSaveStateKey(const AZStd::string& groupName) const;
|
||||
bool IsInstanceNodePropertyModifed(const AzToolsFramework::InstanceDataNode* node) const;
|
||||
const char* GetInstanceNodePropertyIndicator(const AzToolsFramework::InstanceDataNode* node) const;
|
||||
|
||||
// AtomToolsDocumentNotificationBus::Handler implementation
|
||||
void OnDocumentOpened(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentObjectInfoChanged(
|
||||
const AZ::Uuid& documentId, const AtomToolsFramework::DocumentObjectInfo& objectInfo, bool rebuilt) override;
|
||||
|
||||
// AzToolsFramework::IPropertyEditorNotify overrides...
|
||||
void BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode) override;
|
||||
void AfterPropertyModified([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode) override {}
|
||||
void SetPropertyEditingActive([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode) override {}
|
||||
void SetPropertyEditingComplete(AzToolsFramework::InstanceDataNode* pNode) override;
|
||||
void SealUndoStack() override {}
|
||||
void RequestPropertyContextMenu([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode, const QPoint&) override {}
|
||||
void PropertySelectionChanged([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode, bool) override {}
|
||||
|
||||
const AZ::Crc32 m_toolId = {};
|
||||
|
||||
// Tracking the property that is activiley being edited in the inspector
|
||||
const AtomToolsFramework::DynamicProperty* m_activeProperty = {};
|
||||
|
||||
AZ::Uuid m_documentId = AZ::Uuid::CreateNull();
|
||||
AZStd::string m_documentPath;
|
||||
AZStd::intrusive_ptr<MaterialEditorWindowSettings> m_windowSettings;
|
||||
};
|
||||
} // namespace MaterialEditor
|
||||
Loading…
Reference in New Issue