Added support for expanding/collapsing material inspector groups by name
Saving/restoring material inspector group expansion state
This commit is contained in:
+3
-1
@@ -29,11 +29,13 @@ namespace AtomToolsFramework
|
||||
AZ_CLASS_ALLOCATOR(InspectorGroupHeaderWidget, AZ::SystemAllocator, 0);
|
||||
|
||||
explicit InspectorGroupHeaderWidget(QWidget* parent = nullptr);
|
||||
void SetExpanded(bool expanded);
|
||||
void SetExpanded(bool expand);
|
||||
bool IsExpanded() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void clicked(QMouseEvent* event);
|
||||
void expanded();
|
||||
void collapsed();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
|
||||
+9
@@ -56,6 +56,15 @@ namespace AtomToolsFramework
|
||||
//! Calls Rebuild for all InspectorGroupWidget, allowing for destructive UI changes
|
||||
virtual void RebuildAll() = 0;
|
||||
|
||||
//! Expands a specific group
|
||||
virtual void ExpandGroup(const AZStd::string& groupNameId) = 0;
|
||||
|
||||
//! Collapses a specific group
|
||||
virtual void CollapseGroup(const AZStd::string& groupNameId) = 0;
|
||||
|
||||
//! Checks the expansion state of a specific group
|
||||
virtual bool IsGroupExpanded(const AZStd::string& groupNameId) const = 0;
|
||||
|
||||
//! Expands all groups and headers
|
||||
virtual void ExpandAll() = 0;
|
||||
|
||||
|
||||
+11
-4
@@ -63,15 +63,22 @@ namespace AtomToolsFramework
|
||||
void RefreshAll() override;
|
||||
void RebuildAll() override;
|
||||
|
||||
void ExpandGroup(const AZStd::string& groupNameId) override;
|
||||
void CollapseGroup(const AZStd::string& groupNameId) override;
|
||||
bool IsGroupExpanded(const AZStd::string& groupNameId) const override;
|
||||
|
||||
void ExpandAll() override;
|
||||
void CollapseAll() override;
|
||||
|
||||
private:
|
||||
void OnHeaderClicked(QMouseEvent* event, InspectorGroupHeaderWidget* groupHeader, QWidget* groupWidget);
|
||||
protected:
|
||||
virtual bool ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const;
|
||||
virtual void OnGroupExpanded(const AZStd::string& groupNameId);
|
||||
virtual void OnGroupCollapsed(const AZStd::string& groupNameId);
|
||||
virtual void OnHeaderClicked(const AZStd::string& groupNameId, QMouseEvent* event);
|
||||
|
||||
private:
|
||||
QVBoxLayout* m_layout = nullptr;
|
||||
QScopedPointer<Ui::InspectorWidget> m_ui;
|
||||
AZStd::vector<InspectorGroupHeaderWidget*> m_headers;
|
||||
AZStd::vector<QWidget*> m_groups;
|
||||
AZStd::unordered_map<AZStd::string, AZStd::pair<InspectorGroupHeaderWidget*, QWidget*>> m_groups;
|
||||
};
|
||||
} // namespace AtomToolsFramework
|
||||
|
||||
+14
-3
@@ -33,10 +33,21 @@ namespace AtomToolsFramework
|
||||
setMargin(0);
|
||||
}
|
||||
|
||||
void InspectorGroupHeaderWidget::SetExpanded(bool expanded)
|
||||
void InspectorGroupHeaderWidget::SetExpanded(bool expand)
|
||||
{
|
||||
m_expanded = expanded;
|
||||
update();
|
||||
if (m_expanded != expand)
|
||||
{
|
||||
m_expanded = expand;
|
||||
if (m_expanded)
|
||||
{
|
||||
emit expanded();
|
||||
}
|
||||
else
|
||||
{
|
||||
emit collapsed();
|
||||
}
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
bool InspectorGroupHeaderWidget::IsExpanded() const
|
||||
|
||||
@@ -39,7 +39,6 @@ namespace AtomToolsFramework
|
||||
m_layout = new QVBoxLayout(m_ui->m_propertyContent);
|
||||
m_layout->setContentsMargins(0, 0, 0, 0);
|
||||
m_layout->setSpacing(0);
|
||||
m_headers.clear();
|
||||
m_groups.clear();
|
||||
}
|
||||
|
||||
@@ -70,16 +69,27 @@ namespace AtomToolsFramework
|
||||
groupHeader->setText(groupDisplayName.c_str());
|
||||
groupHeader->setToolTip(groupDescription.c_str());
|
||||
m_layout->addWidget(groupHeader);
|
||||
m_headers.push_back(groupHeader);
|
||||
|
||||
groupWidget->setObjectName(groupNameId.c_str());
|
||||
groupWidget->setParent(m_ui->m_propertyContent);
|
||||
m_layout->addWidget(groupWidget);
|
||||
m_groups.push_back(groupWidget);
|
||||
|
||||
connect(groupHeader, &InspectorGroupHeaderWidget::clicked, this, [this, groupHeader, groupWidget](QMouseEvent* event) {
|
||||
OnHeaderClicked(event, groupHeader, groupWidget);
|
||||
m_groups[groupNameId] = AZStd::make_pair(groupHeader, groupWidget);
|
||||
|
||||
connect(groupHeader, &InspectorGroupHeaderWidget::clicked, this, [this, groupNameId](QMouseEvent* event) {
|
||||
OnHeaderClicked(groupNameId, event);
|
||||
});
|
||||
connect(groupHeader, &InspectorGroupHeaderWidget::expanded, this, [this, groupNameId]() { OnGroupExpanded(groupNameId); });
|
||||
connect(groupHeader, &InspectorGroupHeaderWidget::collapsed, this, [this, groupNameId]() { OnGroupCollapsed(groupNameId); });
|
||||
|
||||
if (ShouldGroupAutoExpanded(groupNameId))
|
||||
{
|
||||
ExpandGroup(groupNameId);
|
||||
}
|
||||
else
|
||||
{
|
||||
CollapseGroup(groupNameId);
|
||||
}
|
||||
}
|
||||
|
||||
void InspectorWidget::RefreshGroup(const AZStd::string& groupNameId)
|
||||
@@ -114,50 +124,86 @@ namespace AtomToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void InspectorWidget::ExpandGroup(const AZStd::string& groupNameId)
|
||||
{
|
||||
auto groupItr = m_groups.find(groupNameId);
|
||||
if (groupItr != m_groups.end())
|
||||
{
|
||||
groupItr->second.first->SetExpanded(true);
|
||||
groupItr->second.second->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
void InspectorWidget::CollapseGroup(const AZStd::string& groupNameId)
|
||||
{
|
||||
auto groupItr = m_groups.find(groupNameId);
|
||||
if (groupItr != m_groups.end())
|
||||
{
|
||||
groupItr->second.first->SetExpanded(false);
|
||||
groupItr->second.second->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool InspectorWidget::IsGroupExpanded(const AZStd::string& groupNameId) const
|
||||
{
|
||||
auto groupItr = m_groups.find(groupNameId);
|
||||
return groupItr != m_groups.end() ? groupItr->second.first->IsExpanded() : false;
|
||||
}
|
||||
|
||||
void InspectorWidget::ExpandAll()
|
||||
{
|
||||
for (auto headerWidget : m_headers)
|
||||
for (auto& groupPair : m_groups)
|
||||
{
|
||||
headerWidget->SetExpanded(true);
|
||||
}
|
||||
for (auto groupWidget : m_groups)
|
||||
{
|
||||
groupWidget->setVisible(true);
|
||||
groupPair.second.first->SetExpanded(true);
|
||||
groupPair.second.second->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
void InspectorWidget::CollapseAll()
|
||||
{
|
||||
for (auto headerWidget : m_headers)
|
||||
for (auto& groupPair : m_groups)
|
||||
{
|
||||
headerWidget->SetExpanded(false);
|
||||
}
|
||||
for (auto groupWidget : m_groups)
|
||||
{
|
||||
groupWidget->setVisible(false);
|
||||
groupPair.second.first->SetExpanded(false);
|
||||
groupPair.second.second->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void InspectorWidget::OnHeaderClicked(QMouseEvent* event, InspectorGroupHeaderWidget* groupHeader, QWidget* groupWidget)
|
||||
bool InspectorWidget::ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const
|
||||
{
|
||||
AZ_UNUSED(groupNameId);
|
||||
return true;
|
||||
}
|
||||
|
||||
void InspectorWidget::OnGroupExpanded(const AZStd::string& groupNameId)
|
||||
{
|
||||
AZ_UNUSED(groupNameId);
|
||||
}
|
||||
|
||||
void InspectorWidget::OnGroupCollapsed(const AZStd::string& groupNameId)
|
||||
{
|
||||
AZ_UNUSED(groupNameId);
|
||||
}
|
||||
|
||||
void InspectorWidget::OnHeaderClicked(const AZStd::string& groupNameId, QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::MouseButton::LeftButton)
|
||||
{
|
||||
groupHeader->SetExpanded(!groupHeader->IsExpanded());
|
||||
groupWidget->setVisible(groupHeader->IsExpanded());
|
||||
if (!IsGroupExpanded(groupNameId))
|
||||
{
|
||||
ExpandGroup(groupNameId);
|
||||
}
|
||||
else
|
||||
{
|
||||
CollapseGroup(groupNameId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->button() == Qt::MouseButton::RightButton)
|
||||
{
|
||||
QMenu menu;
|
||||
menu.addAction("Expand", [groupHeader, groupWidget]() {
|
||||
groupHeader->SetExpanded(true);
|
||||
groupWidget->setVisible(true);
|
||||
})->setEnabled(!groupHeader->IsExpanded());
|
||||
menu.addAction("Collapse", [groupHeader, groupWidget]() {
|
||||
groupHeader->SetExpanded(false);
|
||||
groupWidget->setVisible(false);
|
||||
})->setEnabled(groupHeader->IsExpanded());
|
||||
menu.addAction("Expand", [this, groupNameId]() { ExpandGroup(groupNameId); })->setEnabled(!IsGroupExpanded(groupNameId));
|
||||
menu.addAction("Collapse", [this, groupNameId]() { CollapseGroup(groupNameId); })->setEnabled(IsGroupExpanded(groupNameId));
|
||||
menu.addAction("Expand All", [this]() { ExpandAll(); });
|
||||
menu.addAction("Collapse All", [this]() { CollapseAll(); });
|
||||
menu.exec(event->globalPos());
|
||||
|
||||
@@ -30,5 +30,6 @@ namespace MaterialEditor
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AZStd::vector<char> m_mainWindowState;
|
||||
AZStd::unordered_set<AZ::u32> m_inspectorCollapsedGroups;
|
||||
};
|
||||
} // namespace MaterialEditor
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace MaterialEditor
|
||||
|
||||
// Restore additional state for docked windows
|
||||
auto windowSettings = AZ::UserSettings::CreateFind<MaterialEditorWindowSettings>(
|
||||
AZ::Crc32("MaterialEditorwindowSettings"), AZ::UserSettings::CT_GLOBAL);
|
||||
AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL);
|
||||
|
||||
if (!windowSettings->m_mainWindowState.empty())
|
||||
{
|
||||
@@ -272,7 +272,7 @@ namespace MaterialEditor
|
||||
|
||||
// Capture docking state before shutdown
|
||||
auto windowSettings = AZ::UserSettings::CreateFind<MaterialEditorWindowSettings>(
|
||||
AZ::Crc32("MaterialEditorwindowSettings"), AZ::UserSettings::CT_GLOBAL);
|
||||
AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL);
|
||||
|
||||
QByteArray windowState = m_advancedDockManager->saveState();
|
||||
windowSettings->m_mainWindowState.assign(windowState.begin(), windowState.end());
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace MaterialEditor
|
||||
serializeContext->Class<MaterialEditorWindowSettings, AZ::UserSettings>()
|
||||
->Version(1)
|
||||
->Field("mainWindowState", &MaterialEditorWindowSettings::m_mainWindowState)
|
||||
->Field("inspectorCollapsedGroups", &MaterialEditorWindowSettings::m_inspectorCollapsedGroups)
|
||||
;
|
||||
|
||||
if (auto editContext = serializeContext->GetEditContext())
|
||||
|
||||
+42
-26
@@ -21,13 +21,17 @@
|
||||
#include <AtomToolsFramework/Inspector/InspectorPropertyGroupWidget.h>
|
||||
#include <AtomToolsFramework/Util/MaterialPropertyUtil.h>
|
||||
|
||||
#include <Source/Window/MaterialInspector/MaterialInspector.h>
|
||||
#include <Atom/Window/MaterialEditorWindowSettings.h>
|
||||
#include <Window/MaterialInspector/MaterialInspector.h>
|
||||
|
||||
namespace MaterialEditor
|
||||
{
|
||||
MaterialInspector::MaterialInspector(QWidget* parent)
|
||||
: AtomToolsFramework::InspectorWidget(parent)
|
||||
{
|
||||
m_windowSettings = AZ::UserSettings::CreateFind<MaterialEditorWindowSettings>(
|
||||
AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL);
|
||||
|
||||
MaterialDocumentNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
@@ -47,6 +51,22 @@ namespace MaterialEditor
|
||||
AtomToolsFramework::InspectorWidget::Reset();
|
||||
}
|
||||
|
||||
bool MaterialInspector::ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const
|
||||
{
|
||||
auto stateItr = m_windowSettings->m_inspectorCollapsedGroups.find(GetGroupSaveStateKey(groupNameId));
|
||||
return stateItr == m_windowSettings->m_inspectorCollapsedGroups.end();
|
||||
}
|
||||
|
||||
void MaterialInspector::OnGroupExpanded(const AZStd::string& groupNameId)
|
||||
{
|
||||
m_windowSettings->m_inspectorCollapsedGroups.erase(GetGroupSaveStateKey(groupNameId));
|
||||
}
|
||||
|
||||
void MaterialInspector::OnGroupCollapsed(const AZStd::string& groupNameId)
|
||||
{
|
||||
m_windowSettings->m_inspectorCollapsedGroups.insert(GetGroupSaveStateKey(groupNameId));
|
||||
}
|
||||
|
||||
void MaterialInspector::OnDocumentOpened(const AZ::Uuid& documentId)
|
||||
{
|
||||
AddGroupsBegin();
|
||||
@@ -73,6 +93,20 @@ namespace MaterialEditor
|
||||
AddGroupsEnd();
|
||||
}
|
||||
|
||||
AZ::Crc32 MaterialInspector::GetGroupSaveStateKey(const AZStd::string& groupNameId) const
|
||||
{
|
||||
return AZ::Crc32(
|
||||
AZStd::string::format("MaterialInspector::PropertyGroup::%s::%s", m_documentPath.c_str(), groupNameId.c_str()));
|
||||
}
|
||||
|
||||
bool MaterialInspector::CompareInstanceNodeProperties(
|
||||
const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) const
|
||||
{
|
||||
AZ_UNUSED(source);
|
||||
const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(target);
|
||||
return property && AtomToolsFramework::ArePropertyValuesEqual(property->GetValue(), property->GetConfig().m_parentValue);
|
||||
}
|
||||
|
||||
void MaterialInspector::AddDetailsGroup()
|
||||
{
|
||||
const AZ::RPI::MaterialTypeSourceData* materialTypeSourceData = nullptr;
|
||||
@@ -92,15 +126,9 @@ namespace MaterialEditor
|
||||
group.m_properties.push_back(property);
|
||||
|
||||
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
|
||||
const AZ::Crc32 saveStateKey(
|
||||
AZStd::string::format("MaterialInspector::PropertyGroup::%s::%s", m_documentPath.c_str(), groupDisplayName.c_str()));
|
||||
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
|
||||
&group, &group, group.TYPEINFO_Uuid(), this, this, saveStateKey,
|
||||
[this](const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) {
|
||||
AZ_UNUSED(source);
|
||||
const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(target);
|
||||
return property && AtomToolsFramework::ArePropertyValuesEqual(property->GetValue(), property->GetConfig().m_parentValue);
|
||||
});
|
||||
&group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupNameId),
|
||||
[this](const auto source, const auto target) { return CompareInstanceNodeProperties(source, target); });
|
||||
AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget);
|
||||
}
|
||||
|
||||
@@ -127,15 +155,9 @@ namespace MaterialEditor
|
||||
}
|
||||
|
||||
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
|
||||
const AZ::Crc32 saveStateKey(
|
||||
AZStd::string::format("MaterialInspector::PropertyGroup::%s::%s", m_documentPath.c_str(), groupDisplayName.c_str()));
|
||||
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
|
||||
&group, &group, group.TYPEINFO_Uuid(), this, this, saveStateKey,
|
||||
[this](const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) {
|
||||
AZ_UNUSED(source);
|
||||
const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(target);
|
||||
return property && AtomToolsFramework::ArePropertyValuesEqual(property->GetValue(), property->GetConfig().m_parentValue);
|
||||
});
|
||||
&group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupNameId),
|
||||
[this](const auto source, const auto target) { return CompareInstanceNodeProperties(source, target); });
|
||||
AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget);
|
||||
}
|
||||
|
||||
@@ -165,15 +187,9 @@ namespace MaterialEditor
|
||||
}
|
||||
|
||||
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
|
||||
const AZ::Crc32 saveStateKey(
|
||||
AZStd::string::format("MaterialInspector::PropertyGroup::%s::%s", m_documentPath.c_str(), groupDisplayName.c_str()));
|
||||
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
|
||||
&group, &group, group.TYPEINFO_Uuid(), this, this, saveStateKey,
|
||||
[this](const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) {
|
||||
AZ_UNUSED(source);
|
||||
const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(target);
|
||||
return property && AtomToolsFramework::ArePropertyValuesEqual(property->GetValue(), property->GetConfig().m_parentValue);
|
||||
});
|
||||
&group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupNameId),
|
||||
[this](const auto source, const auto target) { return CompareInstanceNodeProperties(source, target); });
|
||||
AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget);
|
||||
}
|
||||
}
|
||||
@@ -270,4 +286,4 @@ namespace MaterialEditor
|
||||
}
|
||||
} // namespace MaterialEditor
|
||||
|
||||
#include <Source/Window/MaterialInspector/moc_MaterialInspector.cpp>
|
||||
#include <Window/MaterialInspector/moc_MaterialInspector.cpp>
|
||||
|
||||
+10
@@ -41,7 +41,16 @@ namespace MaterialEditor
|
||||
// AtomToolsFramework::InspectorRequestBus::Handler overrides...
|
||||
void Reset() override;
|
||||
|
||||
protected:
|
||||
bool ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const override;
|
||||
void OnGroupExpanded(const AZStd::string& groupNameId) override;
|
||||
void OnGroupCollapsed(const AZStd::string& groupNameId) override;
|
||||
|
||||
private:
|
||||
AZ::Crc32 GetGroupSaveStateKey(const AZStd::string& groupNameId) const;
|
||||
bool CompareInstanceNodeProperties(
|
||||
const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) const;
|
||||
|
||||
void AddDetailsGroup();
|
||||
void AddUvNamesGroup();
|
||||
void AddPropertiesGroup();
|
||||
@@ -66,5 +75,6 @@ namespace MaterialEditor
|
||||
AZ::Uuid m_documentId = AZ::Uuid::CreateNull();
|
||||
AZStd::string m_documentPath;
|
||||
AZStd::unordered_map<AZStd::string, AtomToolsFramework::DynamicPropertyGroup> m_groups;
|
||||
AZStd::intrusive_ptr<MaterialEditorWindowSettings> m_windowSettings;
|
||||
};
|
||||
} // namespace MaterialEditor
|
||||
|
||||
+2
-2
@@ -215,7 +215,7 @@ namespace AZ
|
||||
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
|
||||
const AZ::Crc32 saveStateKey(AZStd::string::format(
|
||||
"MaterialPropertyInspector::PropertyGroup::%s::%s", m_materialAssetId.ToString<AZStd::string>().c_str(),
|
||||
groupDisplayName.c_str()));
|
||||
groupNameId.c_str()));
|
||||
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
|
||||
&group, &group, group.TYPEINFO_Uuid(), this, this, saveStateKey,
|
||||
[this](const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) {
|
||||
@@ -268,7 +268,7 @@ namespace AZ
|
||||
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
|
||||
const AZ::Crc32 saveStateKey(AZStd::string::format(
|
||||
"MaterialPropertyInspector::PropertyGroup::%s::%s", m_materialAssetId.ToString<AZStd::string>().c_str(),
|
||||
groupDisplayName.c_str()));
|
||||
groupNameId.c_str()));
|
||||
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
|
||||
&group, &group, group.TYPEINFO_Uuid(), this, this, saveStateKey,
|
||||
[this](const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) {
|
||||
|
||||
Reference in New Issue
Block a user