merge from main

This commit is contained in:
greerdv
2021-05-19 12:14:25 +01:00
11816 changed files with 189923 additions and 1002401 deletions
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/beveledcone.azmodel"
}
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/beveledcube.azmodel"
}
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/beveledcylinder.azmodel"
}
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/caduceus.azmodel"
}
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/cone.azmodel"
}
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/cube.azmodel"
}
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/cylinder.azmodel"
}
}
}
}
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ac53da9855838fcf6782c990247c69c14c2ff5c10624dc5afe89617def9cc7ca
size 9021888
@@ -0,0 +1,15 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "AZ::Render::ModelPreset",
"ClassData": {
"displayName": "Hermanubis",
"modelAsset": {
"assetId": {
"guid": "{1F650917-AA74-5107-9C49-648C957B33DA}",
"subId": 275904906
},
"assetHint": "materialeditor/viewportmodels/Hermanubis.azmodel"
}
}
}
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ec4187f51a4b598fc075f48dd7edb7728b14b285a95530228428a8c3f43c25fc
size 10931856
@@ -1,15 +0,0 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "AZ::Render::ModelPreset",
"ClassData": {
"displayName": "Lucy",
"modelAsset": {
"assetId": {
"guid": "{CF4634D9-EC73-51D4-8F8E-AA25E7A6561A}",
"subId": 277335264
},
"assetHint": "materialeditor/viewportmodels/lucy.azmodel"
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/plane_1x1.azmodel"
}
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/plane_3x3.azmodel"
}
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/platonicsphere.azmodel"
}
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/polarsphere.azmodel"
}
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/quadsphere.azmodel"
}
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/shaderball.azmodel"
}
}
}
}
@@ -12,4 +12,4 @@
"assetHint": "materialeditor/viewportmodels/torus.azmodel"
}
}
}
}
@@ -93,6 +93,7 @@ ly_add_target(
ly_add_target(
NAME MaterialEditor EXECUTABLE
NAMESPACE Gem
AUTOMOC
FILES_CMAKE
materialeditor_files.cmake
Source/Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
@@ -0,0 +1,35 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/Memory/Memory.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/UserSettings/UserSettings.h>
#endif
namespace MaterialEditor
{
struct MaterialDocumentSettings
: public AZ::UserSettings
{
AZ_RTTI(MaterialDocumentSettings, "{FA4F4BF3-BF39-4753-AAF7-AF383B868881}", 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,49 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/any.h>
#include <AzCore/Outcome/Outcome.h>
namespace MaterialEditor
{
class MaterialEditorSettingsRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual AZ::Outcome<AZStd::any> GetProperty(AZStd::string_view name) const = 0;
virtual AZ::Outcome<AZStd::string> GetStringProperty(AZStd::string_view name) const = 0;
virtual AZ::Outcome<bool> GetBoolProperty(AZStd::string_view name) const = 0;
virtual void SetProperty(AZStd::string_view name, const AZStd::any& value) = 0;
virtual void SetStringProperty(AZStd::string_view name, AZStd::string_view stringValue) = 0;
virtual void SetBoolProperty(AZStd::string_view name, bool boolValue) = 0;
};
using MaterialEditorSettingsRequestBus = AZ::EBus<MaterialEditorSettingsRequests>;
class MaterialEditorSettingsNotifications
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual void OnPropertyChanged(AZStd::string_view name, const AZStd::any& value) = 0;
};
using MaterialEditorSettingsNotificationBus = AZ::EBus<MaterialEditorSettingsNotifications>;
} // namespace MaterialEditor
@@ -11,8 +11,8 @@
*/
#pragma once
#include <ACES/Aces.h>
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <Atom/Feature/Utils/LightingPreset.h>
#include <Atom/Feature/Utils/ModelPreset.h>
@@ -66,6 +66,9 @@ namespace MaterialEditor
//! Notify when field of view changes
virtual void OnFieldOfViewChanged([[maybe_unused]] float fieldOfView) {}
//! Notify when tone mapping changes
virtual void OnDisplayMapperOperationTypeChanged([[maybe_unused]] AZ::Render::DisplayMapperOperationType operationType) {}
};
using MaterialViewportNotificationBus = AZ::EBus<MaterialViewportNotifications>;
@@ -11,6 +11,7 @@
*/
#pragma once
#include <ACES/Aces.h>
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/containers/set.h>
#include <AzCore/std/string/string.h>
@@ -147,6 +148,12 @@ namespace MaterialEditor
//! Get field of view
virtual float GetFieldOfView() const = 0;
//! Set tone mapping type
virtual void SetDisplayMapperOperationType(AZ::Render::DisplayMapperOperationType operationType) = 0;
//! Get tone mapping type
virtual AZ::Render::DisplayMapperOperationType GetDisplayMapperOperationType() const = 0;
};
using MaterialViewportRequestBus = AZ::EBus<MaterialViewportRequests>;
@@ -0,0 +1,41 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <ACES/Aces.h>
#include <AzCore/Memory/Memory.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/UserSettings/UserSettings.h>
#endif
namespace MaterialEditor
{
struct MaterialViewportSettings
: public AZ::UserSettings
{
AZ_RTTI(MaterialViewportSettings, "{16150503-A314-4765-82A3-172670C9EA90}", AZ::UserSettings);
AZ_CLASS_ALLOCATOR(MaterialViewportSettings, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* context);
bool m_enableGrid = true;
bool m_enableShadowCatcher = true;
bool m_enableAlternateSkybox = false;
float m_fieldOfView = 90.0f;
AZ::Render::DisplayMapperOperationType m_displayMapperOperationType = AZ::Render::DisplayMapperOperationType::Aces;
AZStd::string m_selectedModelPresetName = "Shader Ball";
AZStd::string m_selectedLightingPresetName = "Neutral Urban";
};
} // namespace MaterialEditor
@@ -28,6 +28,9 @@ namespace MaterialEditor
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//! Bring main window to foreground
virtual void ActivateWindow() = 0;
//! Add dockable widget in main window
//! @param name title of the dockable window
//! @param widget docked window content
@@ -0,0 +1,35 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/Memory/Memory.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/UserSettings/UserSettings.h>
#endif
namespace MaterialEditor
{
struct MaterialEditorWindowSettings
: public AZ::UserSettings
{
AZ_RTTI(MaterialEditorWindowSettings, "{BB9DEB77-B7BE-4DF5-9FDD-6D9F3136C4EA}", AZ::UserSettings);
AZ_CLASS_ALLOCATOR(MaterialEditorWindowSettings, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* context);
AZStd::vector<char> m_mainWindowState;
AZStd::unordered_set<AZ::u32> m_inspectorCollapsedGroups;
};
} // namespace MaterialEditor
@@ -762,6 +762,8 @@ namespace MaterialEditor
// in the hierarchy are applied
m_materialTypeSourceData.EnumerateProperties([this, &parentPropertyValues](const AZStd::string& groupNameId, const AZStd::string& propertyNameId, const auto& propertyDefinition) {
AtomToolsFramework::DynamicPropertyConfig propertyConfig;
// Assign id before conversion so it can be used in dynamic description
propertyConfig.m_id = MaterialPropertyId(groupNameId, propertyNameId).GetCStr();
const auto& propertyIndex = m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyConfig.m_id);
@@ -771,8 +773,10 @@ namespace MaterialEditor
if (propertyIndexInBounds)
{
AtomToolsFramework::ConvertToPropertyConfig(propertyConfig, propertyDefinition);
propertyConfig.m_showThumbnail = true;
propertyConfig.m_originalValue = AtomToolsFramework::ConvertToEditableType(m_materialAsset->GetPropertyValues()[propertyIndex.GetIndex()]);
propertyConfig.m_parentValue = AtomToolsFramework::ConvertToEditableType(parentPropertyValues[propertyIndex.GetIndex()]);
propertyConfig.m_groupName = m_materialTypeSourceData.FindGroup(groupNameId)->m_displayName;
m_properties[propertyConfig.m_id] = AtomToolsFramework::DynamicProperty(propertyConfig);
}
return true;
@@ -789,7 +793,9 @@ namespace MaterialEditor
propertyConfig.m_id = "details.materialType";
propertyConfig.m_nameId = "materialType";
propertyConfig.m_displayName = "Material Type";
propertyConfig.m_description = propertyConfig.m_displayName;
propertyConfig.m_groupName = "Details";
propertyConfig.m_description = "The material type defines the layout, properties, default values, shader connections, and other "
"data needed to create and edit a derived material.";
propertyConfig.m_defaultValue = AZStd::any(materialTypeAsset);
propertyConfig.m_originalValue = propertyConfig.m_defaultValue;
propertyConfig.m_parentValue = propertyConfig.m_defaultValue;
@@ -802,11 +808,14 @@ namespace MaterialEditor
propertyConfig.m_id = "details.parentMaterial";
propertyConfig.m_nameId = "parentMaterial";
propertyConfig.m_displayName = "Parent Material";
propertyConfig.m_description = propertyConfig.m_displayName;
propertyConfig.m_groupName = "Details";
propertyConfig.m_description =
"The parent material provides an initial configuration whose properties are inherited and overriden by a derived material.";
propertyConfig.m_defaultValue = AZStd::any(parentMaterialAsset);
propertyConfig.m_originalValue = propertyConfig.m_defaultValue;
propertyConfig.m_parentValue = propertyConfig.m_defaultValue;
propertyConfig.m_readOnly = true;
propertyConfig.m_showThumbnail = true;
m_properties[propertyConfig.m_id] = AtomToolsFramework::DynamicProperty(propertyConfig);
@@ -822,6 +831,7 @@ namespace MaterialEditor
propertyConfig.m_id = MaterialPropertyId(UvGroupName, shaderInput).GetCStr();
propertyConfig.m_nameId = shaderInput;
propertyConfig.m_displayName = shaderInput;
propertyConfig.m_groupName = "UV Names";
propertyConfig.m_description = shaderInput;
propertyConfig.m_defaultValue = uvName;
propertyConfig.m_originalValue = uvName;
@@ -13,7 +13,6 @@
#include <Atom/Document/MaterialDocumentModule.h>
#include <Document/MaterialDocumentSystemComponent.h>
#include <AzFramework/TargetManagement/TargetManagementComponent.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h>
#include <AzToolsFramework/Asset/AssetSystemComponent.h>
@@ -32,7 +31,6 @@ namespace MaterialEditor
return AZ::ComponentTypeList{
azrtti_typeid<AzToolsFramework::AssetSystem::AssetSystemComponent>(),
azrtti_typeid<MaterialDocumentSystemComponent>(),
azrtti_typeid<AzFramework::TargetManagementComponent>(),
};
}
}
@@ -0,0 +1,54 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/Document/MaterialDocumentSettings.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
namespace MaterialEditor
{
void MaterialDocumentSettings::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<MaterialDocumentSettings, AZ::UserSettings>()
->Version(1)
->Field("showReloadDocumentPrompt", &MaterialDocumentSettings::m_showReloadDocumentPrompt)
->Field("defaultMaterialTypeName", &MaterialDocumentSettings::m_defaultMaterialTypeName)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<MaterialDocumentSettings>(
"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", "")
;
}
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
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")
->Constructor()
->Constructor<const MaterialDocumentSettings&>()
->Property("showReloadDocumentPrompt", BehaviorValueProperty(&MaterialDocumentSettings::m_showReloadDocumentPrompt))
->Property("defaultMaterialTypeName", BehaviorValueProperty(&MaterialDocumentSettings::m_defaultMaterialTypeName))
;
}
}
} // namespace MaterialEditor
@@ -14,6 +14,7 @@
#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>
@@ -40,12 +41,13 @@ AZ_POP_DISABLE_WARNING
namespace MaterialEditor
{
MaterialDocumentSystemComponent::MaterialDocumentSystemComponent()
: m_settings(aznew MaterialEditorSettings)
{
}
void MaterialDocumentSystemComponent::Reflect(AZ::ReflectContext* context)
{
MaterialDocumentSettings::Reflect(context);
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
serialize->Class<MaterialDocumentSystemComponent, AZ::Component>()
@@ -109,7 +111,6 @@ namespace MaterialEditor
void MaterialDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
required.push_back(AZ_CRC("TargetManagerService", 0x6d5708bc));
required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc));
required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601));
required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad));
@@ -133,33 +134,19 @@ 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();
AzFramework::TmMsgBus::Handler::BusConnect(AZ_CRC("OpenInMaterialEditor", 0x9f92aac8));
}
void MaterialDocumentSystemComponent::Deactivate()
{
AZ::TickBus::Handler::BusDisconnect();
AzFramework::TmMsgBus::Handler::BusDisconnect();
MaterialDocumentNotificationBus::Handler::BusDisconnect();
MaterialDocumentSystemRequestBus::Handler::BusDisconnect();
m_documentMap.clear();
}
void MaterialDocumentSystemComponent::OnReceivedMsg(AzFramework::TmMsgPtr msg)
{
if (msg->GetId() == AZ_CRC("OpenInMaterialEditor", 0x9f92aac8))
{
const char* documentPath = reinterpret_cast<const char*>(msg->GetCustomBlob());
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, documentPath);
}
else
{
AZ_Assert(false, "We received a message of an unrecognized class type!");
}
}
AZ::Uuid MaterialDocumentSystemComponent::CreateDocument()
{
auto document = AZStd::make_unique<MaterialDocument>();
@@ -204,22 +191,25 @@ namespace MaterialEditor
AZStd::string documentPath;
MaterialDocumentRequestBus::EventResult(documentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
if (QMessageBox::question(QApplication::activeWindow(),
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)
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes))
{
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
continue;
}
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);
}
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);
}
}
@@ -228,22 +218,25 @@ namespace MaterialEditor
AZStd::string documentPath;
MaterialDocumentRequestBus::EventResult(documentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
if (QMessageBox::question(QApplication::activeWindow(),
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)
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes))
{
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
continue;
}
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);
}
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);
}
}
@@ -16,13 +16,12 @@
#include <AzCore/Component/TickBus.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzFramework/TargetManagement/TargetManagementAPI.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>
#include <Document/MaterialEditorSettings.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QFileInfo>
@@ -35,7 +34,6 @@ namespace MaterialEditor
class MaterialDocumentSystemComponent
: public AZ::Component
, private AZ::TickBus::Handler
, private AzFramework::TmMsgBus::Handler
, private MaterialDocumentNotificationBus::Handler
, private MaterialDocumentSystemRequestBus::Handler
{
@@ -45,7 +43,7 @@ namespace MaterialEditor
MaterialDocumentSystemComponent();
~MaterialDocumentSystemComponent() = default;
MaterialDocumentSystemComponent(const MaterialDocumentSystemComponent&) = delete;
MaterialDocumentSystemComponent& operator =(const MaterialDocumentSystemComponent&) = delete;
MaterialDocumentSystemComponent& operator=(const MaterialDocumentSystemComponent&) = delete;
static void Reflect(AZ::ReflectContext* context);
@@ -72,11 +70,6 @@ namespace MaterialEditor
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// AzFramework::TmMsgBus::Handler overrides...
void OnReceivedMsg(AzFramework::TmMsgPtr msg) override;
//////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// MaterialDocumentSystemRequestBus::Handler overrides...
AZ::Uuid CreateDocument() override;
@@ -94,10 +87,10 @@ namespace MaterialEditor
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;
AZStd::unique_ptr<MaterialEditorSettings> m_settings;
const size_t m_maxMessageBoxLineCount = 15;
};
}
} // namespace MaterialEditor
@@ -1,73 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Document/MaterialEditorSettings.h>
namespace MaterialEditor
{
MaterialEditorSettings::MaterialEditorSettings()
{
MaterialEditorSettingsRequestBus::Handler::BusConnect();
}
MaterialEditorSettings::~MaterialEditorSettings()
{
MaterialEditorSettingsRequestBus::Handler::BusDisconnect();
}
AZ::Outcome<AZStd::any> MaterialEditorSettings::GetProperty(AZStd::string_view name) const
{
const auto it = m_propertyMap.find(name);
if (it != m_propertyMap.end())
{
return AZ::Success(it->second);
}
AZ_Warning("MaterialEditorSettings", false, "Failed to find property [%s].", name.data());
return AZ::Failure();
}
AZ::Outcome<AZStd::string> MaterialEditorSettings::GetStringProperty(AZStd::string_view name) const
{
AZ::Outcome<AZStd::any> outcome = GetProperty(name);
if (!outcome || !outcome.GetValue().is<AZStd::string>())
{
return AZ::Failure();
}
return AZ::Success(AZStd::any_cast<AZStd::string>(outcome.GetValue()));
}
AZ::Outcome<bool> MaterialEditorSettings::GetBoolProperty(AZStd::string_view name) const
{
AZ::Outcome<AZStd::any> outcome = GetProperty(name);
if (!outcome || !outcome.GetValue().is<bool>())
{
return AZ::Failure();
}
return AZ::Success(AZStd::any_cast<bool>(outcome.GetValue()));
}
void MaterialEditorSettings::SetProperty(AZStd::string_view name, const AZStd::any& value)
{
m_propertyMap[name] = value;
MaterialEditorSettingsNotificationBus::Broadcast(&MaterialEditorSettingsNotifications::OnPropertyChanged, name, value);
}
void MaterialEditorSettings::SetStringProperty(AZStd::string_view name, AZStd::string_view stringValue)
{
SetProperty(name, AZStd::any(AZStd::string(stringValue)));
}
void MaterialEditorSettings::SetBoolProperty(AZStd::string_view name, bool boolValue)
{
SetProperty(name, AZStd::any(boolValue));
}
}
@@ -1,45 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/std/any.h>
#include <Atom/Document/MaterialEditorSettingsBus.h>
namespace MaterialEditor
{
class MaterialEditorSettings
: public MaterialEditorSettingsRequestBus::Handler
{
public:
AZ_RTTI(MaterialEditorSettings, "{9C6B6E20-A28E-45DD-85BE-68CA35E9305E}");
AZ_CLASS_ALLOCATOR(MaterialEditorSettings, AZ::SystemAllocator, 0);
MaterialEditorSettings();
~MaterialEditorSettings();
AZ::Outcome<AZStd::any> GetProperty(AZStd::string_view name) const override;
AZ::Outcome<AZStd::string> GetStringProperty(AZStd::string_view name) const override;
AZ::Outcome<bool> GetBoolProperty(AZStd::string_view name) const override;
void SetProperty(AZStd::string_view name, const AZStd::any& value) override;
void SetStringProperty(AZStd::string_view name, AZStd::string_view stringValue) override;
void SetBoolProperty(AZStd::string_view name, bool boolValue) override;
private:
AZStd::unordered_map<AZStd::string, AZStd::any> m_propertyMap;
};
} // namespace MaterialEditor
@@ -45,6 +45,7 @@
#include <Atom/Window/MaterialEditorWindowModule.h>
#include <Atom/Window/MaterialEditorWindowFactoryRequestBus.h>
#include <Atom/Window/MaterialEditorWindowRequestBus.h>
#include <AzCore/Utils/Utils.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
@@ -90,6 +91,14 @@ namespace MaterialEditor
});
}
MaterialEditorApplication::~MaterialEditorApplication()
{
AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect();
AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect();
MaterialEditorWindowNotificationBus::Handler::BusDisconnect();
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
}
void MaterialEditorApplication::CreateReflectionManager()
{
Application::CreateReflectionManager();
@@ -275,7 +284,7 @@ namespace MaterialEditor
AZ_Assert(context, "No serialize context");
char resolvedPath[AZ_MAX_PATH_LEN] = "";
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@user@/EditorUserSettings.xml", resolvedPath, AZ_ARRAY_SIZE(resolvedPath));
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@user@/MaterialEditorUserSettings.xml", resolvedPath, AZ_ARRAY_SIZE(resolvedPath));
m_localUserSettings.Save(resolvedPath, context);
}
}
@@ -299,12 +308,19 @@ namespace MaterialEditor
return false;
}
void MaterialEditorApplication::ProcessCommandLine()
void MaterialEditorApplication::ProcessCommandLine(const AZ::CommandLine& commandLine)
{
const AZStd::string timeoputSwitchName = "timeout";
if (m_commandLine.HasSwitch(timeoputSwitchName))
const AZStd::string activateWindowSwitchName = "activatewindow";
if (commandLine.HasSwitch(activateWindowSwitchName))
{
const AZStd::string& timeoutValue = m_commandLine.GetSwitchValue(timeoputSwitchName, 0);
MaterialEditor::MaterialEditorWindowRequestBus::Broadcast(
&MaterialEditor::MaterialEditorWindowRequestBus::Handler::ActivateWindow);
}
const AZStd::string timeoputSwitchName = "timeout";
if (commandLine.HasSwitch(timeoputSwitchName))
{
const AZStd::string& timeoutValue = commandLine.GetSwitchValue(timeoputSwitchName, 0);
const uint32_t timeoutInMs = atoi(timeoutValue.c_str());
AZ_Printf("MaterialEditor", "Timeout scheduled, shutting down in %u ms", timeoutInMs);
QTimer::singleShot(timeoutInMs, [this] {
@@ -315,10 +331,10 @@ namespace MaterialEditor
// Process command line options for running one or more python scripts on startup
const AZStd::string runPythonScriptSwitchName = "runpython";
size_t runPythonScriptCount = m_commandLine.GetNumSwitchValues(runPythonScriptSwitchName);
size_t runPythonScriptCount = commandLine.GetNumSwitchValues(runPythonScriptSwitchName);
for (size_t runPythonScriptIndex = 0; runPythonScriptIndex < runPythonScriptCount; ++runPythonScriptIndex)
{
const AZStd::string runPythonScriptPath = m_commandLine.GetSwitchValue(runPythonScriptSwitchName, runPythonScriptIndex);
const AZStd::string runPythonScriptPath = commandLine.GetSwitchValue(runPythonScriptSwitchName, runPythonScriptIndex);
AZStd::vector<AZStd::string_view> runPythonArgs;
AZ_Printf("MaterialEditor", "Launching script: %s", runPythonScriptPath.c_str());
@@ -329,17 +345,17 @@ namespace MaterialEditor
}
// Process command line options for opening one or more material documents on startup
size_t openDocumentCount = m_commandLine.GetNumMiscValues();
size_t openDocumentCount = commandLine.GetNumMiscValues();
for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex)
{
const AZStd::string openDocumentPath = m_commandLine.GetMiscValue(openDocumentIndex);
const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex);
AZ_Printf("MaterialEditor", "Opening document: %s", openDocumentPath.c_str());
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
}
const AZStd::string exitAfterCommandsSwitchName = "exitaftercommands";
if (m_commandLine.HasSwitch(exitAfterCommandsSwitchName))
if (commandLine.HasSwitch(exitAfterCommandsSwitchName))
{
ExitMainLoop();
}
@@ -409,9 +425,56 @@ namespace MaterialEditor
bool MaterialEditorApplication::LaunchDiscoveryService()
{
const QStringList arguments = { "-fail_silently" };
// Determine if this is the first launch of the tool by attempting to connect to a running server
if (m_socket.Connect(QApplication::applicationName()))
{
// If the server was located, the application is already running.
// Forward commandline options to other application instance.
QByteArray buffer;
buffer.append("ProcessCommandLine:");
return AtomToolsFramework::LaunchTool("GridHub", AZ_TRAIT_MATERIALEDITOR_EXT, arguments);
// Add the command line options from this process to the message, skipping the executable path
for (int argi = 1; argi < m_argC; ++argi)
{
buffer.append(QString(m_argV[argi]).append("\n").toUtf8());
}
// Inject command line option to always bring the main window to the foreground
buffer.append("--activatewindow\n");
m_socket.Send(buffer);
m_socket.Disconnect();
return false;
}
// Setup server to handle basic commands
m_server.SetReadHandler([this](const QByteArray& buffer) {
// Handle commmand line params from connected socket
if (buffer.startsWith("ProcessCommandLine:"))
{
// Remove header and parse commands
AZStd::string params(buffer.data(), buffer.size());
params = params.substr(strlen("ProcessCommandLine:"));
AZStd::vector<AZStd::string> tokens;
AZ::StringFunc::Tokenize(params, tokens, "\n");
if (!tokens.empty())
{
AZ::CommandLine commandLine;
commandLine.Parse(tokens);
ProcessCommandLine(commandLine);
}
}
});
// Launch local server
if (!m_server.Connect(QApplication::applicationName()))
{
return false;
}
return true;
}
void MaterialEditorApplication::StartInternal()
@@ -421,10 +484,14 @@ namespace MaterialEditor
return;
}
//[GFX TODO][ATOM-415] Try to factor out some of this stuff with AtomSampleViewerApplication
WriteStartupLog();
if (!LaunchDiscoveryService())
{
ExitMainLoop();
return;
}
AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusConnect();
AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast(&AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized);
@@ -434,8 +501,6 @@ namespace MaterialEditor
LoadSettings();
LaunchDiscoveryService();
MaterialEditorWindowNotificationBus::Handler::BusConnect();
MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast(
@@ -450,7 +515,7 @@ namespace MaterialEditor
}
// Delay execution of commands and scripts post initialization
QTimer::singleShot(0, [this]() { ProcessCommandLine(); });
QTimer::singleShot(0, [this]() { ProcessCommandLine(m_commandLine); });
}
bool MaterialEditorApplication::GetAssetDatabaseLocation(AZStd::string& result)
@@ -481,6 +546,9 @@ namespace MaterialEditor
void MaterialEditorApplication::Stop()
{
MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast(
&MaterialEditor::MaterialEditorWindowFactoryRequestBus::Handler::DestroyMaterialEditorWindow);
UnloadSettings();
AzFramework::Application::Stop();
}
@@ -12,22 +12,20 @@
#pragma once
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/Window/MaterialEditorWindowNotificationBus.h>
#include <AtomToolsFramework/Communication/LocalServer.h>
#include <AtomToolsFramework/Communication/LocalSocket.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/UserSettings/UserSettingsProvider.h>
#include <AzCore/Debug/TraceMessageBus.h>
#include <AzCore/UserSettings/UserSettingsProvider.h>
#include <AzFramework/Application/Application.h>
#include <AzFramework/Asset/AssetSystemBus.h>
#include <AzFramework/Logging/LogFile.h>
#include <AzToolsFramework/API/AssetDatabaseBus.h>
#include <AzToolsFramework/API/EditorPythonConsoleBus.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/Window/MaterialEditorWindowNotificationBus.h>
#include <QApplication>
#include <QTimer>
@@ -51,7 +49,7 @@ namespace MaterialEditor
using Base = AzFramework::Application;
MaterialEditorApplication(int* argc, char*** argv);
virtual ~MaterialEditorApplication() = default;
virtual ~MaterialEditorApplication();
//////////////////////////////////////////////////////////////////////////
// AzFramework::Application
@@ -110,7 +108,7 @@ namespace MaterialEditor
void CompileCriticalAssets();
void ProcessCommandLine();
void ProcessCommandLine(const AZ::CommandLine& commandLine);
void WriteStartupLog();
void LoadSettings();
@@ -138,5 +136,8 @@ namespace MaterialEditor
bool m_activatedLocalUserSettings = false;
QTimer m_timer;
AtomToolsFramework::LocalSocket m_socket;
AtomToolsFramework::LocalServer m_server;
};
} // namespace MaterialEditor
@@ -9,4 +9,4 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
set(PAL_TRAIT_ATOM_MATERIAL_EDITOR_APPLICATION_SUPPORTED FALSE)
set(PAL_TRAIT_ATOM_MATERIAL_EDITOR_APPLICATION_SUPPORTED FALSE)
@@ -9,4 +9,4 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
set(PAL_TRAIT_ATOM_MATERIAL_EDITOR_APPLICATION_SUPPORTED FALSE)
set(PAL_TRAIT_ATOM_MATERIAL_EDITOR_APPLICATION_SUPPORTED FALSE)
@@ -10,4 +10,4 @@
#
set(GEM_DEPENDENCIES
)
)
@@ -9,4 +9,4 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
set(PAL_TRAIT_ATOM_MATERIAL_EDITOR_APPLICATION_SUPPORTED TRUE)
set(PAL_TRAIT_ATOM_MATERIAL_EDITOR_APPLICATION_SUPPORTED TRUE)
@@ -10,4 +10,4 @@
#
set(GEM_DEPENDENCIES
)
)
@@ -9,4 +9,4 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
set(PAL_TRAIT_ATOM_MATERIAL_EDITOR_APPLICATION_SUPPORTED TRUE)
set(PAL_TRAIT_ATOM_MATERIAL_EDITOR_APPLICATION_SUPPORTED TRUE)
@@ -11,4 +11,4 @@
set(GEM_DEPENDENCIES
Gem::QtForPython.Editor
)
)
@@ -9,4 +9,4 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
set(PAL_TRAIT_ATOM_MATERIAL_EDITOR_APPLICATION_SUPPORTED FALSE)
set(PAL_TRAIT_ATOM_MATERIAL_EDITOR_APPLICATION_SUPPORTED FALSE)
@@ -17,6 +17,8 @@
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/Components/CameraBus.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
@@ -136,6 +138,11 @@ namespace MaterialEditor
const InputChannel::State state = event.m_inputChannel.GetState();
const KeyMask keysOld = m_keys;
bool mouseOver = false;
AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::EventResult(
mouseOver, GetViewportId(),
&AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::IsMouseOver);
if (!m_behavior)
{
EvaluateControlBehavior();
@@ -178,7 +185,10 @@ namespace MaterialEditor
}
else if (inputChannelId == InputDeviceMouse::Movement::Z)
{
m_behavior->MoveZ(event.m_inputChannel.GetValue());
if (mouseOver)
{
m_behavior->MoveZ(event.m_inputChannel.GetValue());
}
}
break;
case InputChannel::State::Ended:
@@ -222,7 +232,10 @@ namespace MaterialEditor
}
else if (inputChannelId == InputDeviceMouse::Movement::Z)
{
m_behavior->MoveZ(event.m_inputChannel.GetValue());
if (mouseOver)
{
m_behavior->MoveZ(event.m_inputChannel.GetValue());
}
}
break;
}
@@ -24,6 +24,7 @@
#include <Viewport/MaterialViewportComponent.h>
#include <Atom/Viewport/MaterialViewportNotificationBus.h>
#include <Atom/Viewport/MaterialViewportSettings.h>
#include <Atom/ImageProcessing/ImageObject.h>
#include <Atom/ImageProcessing/ImageProcessingBus.h>
@@ -70,6 +71,8 @@ namespace MaterialEditor
void MaterialViewportComponent::Reflect(AZ::ReflectContext* context)
{
MaterialViewportSettings::Reflect(context);
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
serialize->Class<MaterialViewportComponent, AZ::Component>()
@@ -160,6 +163,9 @@ namespace MaterialEditor
void MaterialViewportComponent::Activate()
{
m_viewportSettings =
AZ::UserSettings::CreateFind<MaterialViewportSettings>(AZ::Crc32("MaterialViewportSettings"), AZ::UserSettings::CT_GLOBAL);
m_lightingPresetPreviewImageDefault = QImage(180, 90, QImage::Format::Format_RGBA8888);
m_lightingPresetPreviewImageDefault.fill(Qt::GlobalColor::black);
@@ -192,13 +198,14 @@ namespace MaterialEditor
MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnBeginReloadContent);
const AZStd::string prevLightingPresetSelectionName = m_lightingPresetSelection ? m_lightingPresetSelection->m_displayName : "";
const AZStd::string prevModelPresetSelectionName = m_modelPresetSelection ? m_modelPresetSelection->m_displayName : "";
const AZStd::string selectedLightingPresetNameOld = m_viewportSettings->m_selectedLightingPresetName;
m_lightingPresetVector.clear();
m_lightingPresetLastSavePathMap.clear();
m_lightingPresetSelection.reset();
const AZStd::string selectedModelPresetNameOld = m_viewportSettings->m_selectedModelPresetName;
m_modelPresetVector.clear();
m_modelPresetLastSavePathMap.clear();
m_modelPresetSelection.reset();
@@ -263,8 +270,8 @@ namespace MaterialEditor
// If there was a prior selection, this will keep the same configuration selected.
// Otherwise, these strings are empty and the operation will be ignored.
SelectLightingPresetByName(prevLightingPresetSelectionName);
SelectModelPresetByName(prevModelPresetSelectionName);
SelectLightingPresetByName(selectedLightingPresetNameOld);
SelectModelPresetByName(selectedModelPresetNameOld);
MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnEndReloadContent);
@@ -327,6 +334,7 @@ namespace MaterialEditor
if (preset)
{
m_lightingPresetSelection = preset;
m_viewportSettings->m_selectedLightingPresetName = preset->m_displayName;
MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnLightingPresetSelected, m_lightingPresetSelection);
}
}
@@ -422,6 +430,7 @@ namespace MaterialEditor
if (preset)
{
m_modelPresetSelection = preset;
m_viewportSettings->m_selectedModelPresetName = preset->m_displayName;
MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnModelPresetSelected, m_modelPresetSelection);
}
}
@@ -463,60 +472,66 @@ namespace MaterialEditor
void MaterialViewportComponent::SetShadowCatcherEnabled(bool enable)
{
m_shadowCatcherEnabled = enable;
m_viewportSettings->m_enableShadowCatcher = enable;
MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnShadowCatcherEnabledChanged, enable);
}
bool MaterialViewportComponent::GetShadowCatcherEnabled() const
{
return m_shadowCatcherEnabled;
return m_viewportSettings->m_enableShadowCatcher;
}
void MaterialViewportComponent::SetGridEnabled(bool enable)
{
m_gridEnabled = enable;
m_viewportSettings->m_enableGrid = enable;
MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnGridEnabledChanged, enable);
}
bool MaterialViewportComponent::GetGridEnabled() const
{
return m_gridEnabled;
return m_viewportSettings->m_enableGrid;
}
void MaterialViewportComponent::SetAlternateSkyboxEnabled(bool enable)
{
m_alternateSkyboxEnabled = enable;
m_viewportSettings->m_enableAlternateSkybox = enable;
MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnAlternateSkyboxEnabledChanged, enable);
}
bool MaterialViewportComponent::GetAlternateSkyboxEnabled() const
{
return m_alternateSkyboxEnabled;
return m_viewportSettings->m_enableAlternateSkybox;
}
void MaterialViewportComponent::SetFieldOfView(float fieldOfView)
{
m_fieldOfView = fieldOfView;
m_viewportSettings->m_fieldOfView = fieldOfView;
MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnFieldOfViewChanged, fieldOfView);
}
float MaterialViewportComponent::GetFieldOfView() const
{
return m_fieldOfView;
return m_viewportSettings->m_fieldOfView;
}
void MaterialViewportComponent::SetDisplayMapperOperationType(AZ::Render::DisplayMapperOperationType operationType)
{
m_viewportSettings->m_displayMapperOperationType = operationType;
MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnDisplayMapperOperationTypeChanged, operationType);
}
AZ::Render::DisplayMapperOperationType MaterialViewportComponent::GetDisplayMapperOperationType() const
{
return m_viewportSettings->m_displayMapperOperationType;
}
void MaterialViewportComponent::OnCatalogLoaded([[maybe_unused]] const char* catalogFile)
{
AZ::TickBus::QueueFunction([this]() {
ReloadContent();
// Automatically select preferred default presets if they exist
// We will later data drive this with editor settings
SelectLightingPresetByName("Neutral Urban");
SelectModelPresetByName("Shader Ball");
});
}
}
@@ -12,12 +12,13 @@
#pragma once
#include <AzCore/Component/Component.h>
#include <AzFramework/Asset/AssetCatalogBus.h>
#include <ACES/Aces.h>
#include <Atom/Feature/Utils/LightingPreset.h>
#include <Atom/Feature/Utils/ModelPreset.h>
#include <Atom/Viewport/MaterialViewportRequestBus.h>
#include <Atom/Viewport/MaterialViewportSettings.h>
#include <AzCore/Component/Component.h>
#include <AzFramework/Asset/AssetCatalogBus.h>
namespace MaterialEditor
{
@@ -85,6 +86,8 @@ namespace MaterialEditor
bool GetAlternateSkyboxEnabled() const override;
void SetFieldOfView(float fieldOfView) override;
float GetFieldOfView() const override;
void SetDisplayMapperOperationType(AZ::Render::DisplayMapperOperationType operationType) override;
AZ::Render::DisplayMapperOperationType GetDisplayMapperOperationType() const override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@@ -107,9 +110,6 @@ namespace MaterialEditor
mutable AZStd::map<AZ::Render::LightingPresetPtr, AZStd::string> m_lightingPresetLastSavePathMap;
mutable AZStd::map<AZ::Render::ModelPresetPtr, AZStd::string> m_modelPresetLastSavePathMap;
bool m_shadowCatcherEnabled = true;
bool m_gridEnabled = true;
bool m_alternateSkyboxEnabled = false;
float m_fieldOfView = 90.0f;
AZStd::intrusive_ptr<MaterialViewportSettings> m_viewportSettings;
};
}
@@ -34,6 +34,7 @@
#include <Atom/Feature/PostProcessing/PostProcessingConstants.h>
#include <Atom/Feature/PostProcess/PostProcessFeatureProcessorInterface.h>
#include <Atom/Feature/ImageBasedLights/ImageBasedLightFeatureProcessorInterface.h>
#include <Atom/Feature/ACES/AcesDisplayMapperFeatureProcessor.h>
#include <Atom/Component/DebugCamera/NoClipControllerComponent.h>
#include <Atom/Document/MaterialDocumentRequestBus.h>
@@ -41,6 +42,7 @@
#include <Atom/Feature/Utils/ModelPreset.h>
#include <Atom/Viewport/MaterialViewportRequestBus.h>
#include <Atom/Viewport/PerformanceMonitorRequestBus.h>
#include <Atom/Viewport/MaterialViewportSettings.h>
#include <AtomLyIntegration/CommonFeatures/Grid/GridComponentConstants.h>
#include <AtomLyIntegration/CommonFeatures/Grid/GridComponentConfig.h>
@@ -89,10 +91,13 @@ namespace MaterialEditor
m_scene->SetShaderResourceGroupCallback(callback);
// Bind m_defaultScene to the GameEntityContext's AzFramework::Scene
AZStd::vector<AzFramework::Scene*> scenes;
AzFramework::SceneSystemRequestBus::BroadcastResult(scenes, &AzFramework::SceneSystemRequests::GetAllScenes);
AZ_Assert(scenes.size() > 0, "Error: Scenes missing during system component initialization"); // This should never happen unless scene creation has changed.
scenes.at(0)->SetSubsystem(m_scene.get());
auto sceneSystem = AzFramework::SceneSystemInterface::Get();
AZ_Assert(sceneSystem, "MaterialViewportRenderer was unable to get the scene system during construction.");
AZStd::shared_ptr<AzFramework::Scene> mainScene = sceneSystem->GetScene(AzFramework::Scene::MainSceneName);
// This should never happen unless scene creation has changed.
AZ_Assert(mainScene, "Main scenes missing during system component initialization");
mainScene->SetSubsystem(m_scene);
// Create a render pipeline from the specified asset for the window context and add the pipeline to the scene
AZ::Data::Asset<AZ::RPI::AnyAsset> pipelineAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath<AZ::RPI::AnyAsset>(m_defaultPipelineAssetPath.c_str(), AZ::RPI::AssetUtils::TraceLevel::Error);
@@ -136,7 +141,6 @@ namespace MaterialEditor
m_renderPipeline->SetDefaultViewFromEntity(m_cameraEntity->GetId());
// Configure tone mapper
AzFramework::EntityContextRequestBus::EventResult(m_postProcessEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "postProcessEntity");
AZ_Assert(m_postProcessEntity != nullptr, "Failed to create post process entity.");
@@ -146,17 +150,17 @@ namespace MaterialEditor
m_postProcessEntity->Activate();
// Init directional light processor
m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::DirectionalLightFeatureProcessorInterface>();
// Init Skybox
// Init display mapper processor
m_displayMapperFeatureProcessor = m_scene->GetFeatureProcessor<Render::DisplayMapperFeatureProcessorInterface>();
// Init Skybox
m_skyboxFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::SkyBoxFeatureProcessorInterface>();
m_skyboxFeatureProcessor->Enable(true);
m_skyboxFeatureProcessor->SetSkyboxMode(AZ::Render::SkyBoxMode::Cubemap);
// Create IBL
AzFramework::EntityContextRequestBus::EventResult(m_iblEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "IblEntity");
AZ_Assert(m_iblEntity != nullptr, "Failed to create ibl entity.");
@@ -172,8 +176,8 @@ namespace MaterialEditor
m_modelEntity->CreateComponent(AZ::Render::MaterialComponentTypeId);
m_modelEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
m_modelEntity->Activate();
// Create shadow catcher
// Create shadow catcher
AzFramework::EntityContextRequestBus::EventResult(m_shadowCatcherEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportShadowCatcher");
AZ_Assert(m_shadowCatcherEntity != nullptr, "Failed to create shadow catcher entity.");
m_shadowCatcherEntity->CreateComponent(AZ::Render::MeshComponentTypeId);
@@ -205,7 +209,6 @@ namespace MaterialEditor
}
// Create grid
AzFramework::EntityContextRequestBus::EventResult(m_gridEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportGrid");
AZ_Assert(m_gridEntity != nullptr, "Failed to create grid entity.");
@@ -232,13 +235,23 @@ namespace MaterialEditor
MaterialViewportRequestBus::BroadcastResult(modelPreset, &MaterialViewportRequestBus::Events::GetModelPresetSelection);
OnModelPresetSelected(modelPreset);
m_viewportController->Init(m_cameraEntity->GetId(), m_modelEntity->GetId(), m_iblEntity->GetId());
// Apply user settinngs restored since last run
AZStd::intrusive_ptr<MaterialViewportSettings> viewportSettings =
AZ::UserSettings::CreateFind<MaterialViewportSettings>(AZ::Crc32("MaterialViewportSettings"), AZ::UserSettings::CT_GLOBAL);
OnGridEnabledChanged(viewportSettings->m_enableGrid);
OnShadowCatcherEnabledChanged(viewportSettings->m_enableShadowCatcher);
OnAlternateSkyboxEnabledChanged(viewportSettings->m_enableAlternateSkybox);
OnFieldOfViewChanged(viewportSettings->m_fieldOfView);
OnDisplayMapperOperationTypeChanged(viewportSettings->m_displayMapperOperationType);
MaterialDocumentNotificationBus::Handler::BusConnect();
MaterialViewportNotificationBus::Handler::BusConnect();
AZ::TickBus::Handler::BusConnect();
AZ::TransformNotificationBus::MultiHandler::BusConnect(m_cameraEntity->GetId());
AzFramework::WindowSystemRequestBus::Handler::BusConnect();
m_viewportController->Init(m_cameraEntity->GetId(), m_modelEntity->GetId(), m_iblEntity->GetId());
}
MaterialViewportRenderer::~MaterialViewportRenderer()
@@ -277,6 +290,13 @@ namespace MaterialEditor
}
m_lightHandles.clear();
auto sceneSystem = AzFramework::SceneSystemInterface::Get();
AZ_Assert(sceneSystem, "MaterialViewportRenderer was unable to get the scene system during destruction.");
AZStd::shared_ptr<AzFramework::Scene> mainScene = sceneSystem->GetScene(AzFramework::Scene::MainSceneName);
// This should never happen unless scene creation has changed.
AZ_Assert(mainScene, "Main scenes missing during system component destruction");
mainScene->UnsetSubsystem(m_scene);
m_swapChainPass = nullptr;
AZ::RPI::RPISystemInterface::Get()->UnregisterScene(m_scene);
m_scene = nullptr;
@@ -416,6 +436,13 @@ namespace MaterialEditor
MaterialEditorViewportInputControllerRequestBus::Broadcast(&MaterialEditorViewportInputControllerRequestBus::Handler::SetFieldOfView, fieldOfView);
}
void MaterialViewportRenderer::OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType)
{
AZ::Render::DisplayMapperConfigurationDescriptor desc;
desc.m_operationType = operationType;
m_displayMapperFeatureProcessor->RegisterDisplayMapperConfiguration(desc);
}
void MaterialViewportRenderer::OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset)
{
if (m_modelAssetId == asset.GetId())
@@ -27,6 +27,11 @@
namespace AZ
{
namespace Render
{
class DisplayMapperFeatureProcessorInterface;
}
class Entity;
class Component;
@@ -71,6 +76,7 @@ namespace MaterialEditor
void OnGridEnabledChanged(bool enable) override;
void OnAlternateSkyboxEnabledChanged(bool enable) override;
void OnFieldOfViewChanged(float fieldOfView) override;
void OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) override;
// AZ::Data::AssetBus::Handler interface overrides...
void OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
@@ -92,6 +98,7 @@ namespace MaterialEditor
AZ::RPI::RenderPipelinePtr m_renderPipeline;
AZ::RPI::ScenePtr m_scene;
AZ::Render::DirectionalLightFeatureProcessorInterface* m_directionalLightFeatureProcessor = nullptr;
AZ::Render::DisplayMapperFeatureProcessorInterface* m_displayMapperFeatureProcessor = nullptr;
AZ::Entity* m_cameraEntity = nullptr;
AZ::Component* m_cameraComponent = nullptr;
@@ -0,0 +1,72 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/Viewport/MaterialViewportSettings.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
namespace MaterialEditor
{
void MaterialViewportSettings::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<MaterialViewportSettings, AZ::UserSettings>()
->Version(1)
->Field("enableGrid", &MaterialViewportSettings::m_enableGrid)
->Field("enableShadowCatcher", &MaterialViewportSettings::m_enableShadowCatcher)
->Field("enableAlternateSkybox", &MaterialViewportSettings::m_enableAlternateSkybox)
->Field("fieldOfView", &MaterialViewportSettings::m_fieldOfView)
->Field("displayMapperOperationType", &MaterialViewportSettings::m_displayMapperOperationType)
->Field("selectedModelPresetName", &MaterialViewportSettings::m_selectedModelPresetName)
->Field("selectedLightingPresetName", &MaterialViewportSettings::m_selectedLightingPresetName)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<MaterialViewportSettings>(
"MaterialViewportSettings", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialViewportSettings::m_enableGrid, "Enable Grid", "")
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialViewportSettings::m_enableShadowCatcher, "Enable Shadow Catcher", "")
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialViewportSettings::m_enableAlternateSkybox, "Enable Alternate Skybox", "")
->DataElement(AZ::Edit::UIHandlers::Slider, &MaterialViewportSettings::m_fieldOfView, "Field Of View", "")
->Attribute(AZ::Edit::Attributes::Min, 60.0f)
->Attribute(AZ::Edit::Attributes::Max, 120.0f)
->DataElement(AZ::Edit::UIHandlers::ComboBox, &MaterialViewportSettings::m_displayMapperOperationType, "Display Mapper Type", "")
->EnumAttribute(AZ::Render::DisplayMapperOperationType::Aces, "Aces")
->EnumAttribute(AZ::Render::DisplayMapperOperationType::AcesLut, "AcesLut")
->EnumAttribute(AZ::Render::DisplayMapperOperationType::Passthrough, "Passthrough")
->EnumAttribute(AZ::Render::DisplayMapperOperationType::GammaSRGB, "GammaSRGB")
->EnumAttribute(AZ::Render::DisplayMapperOperationType::Reinhard, "Reinhard")
;
}
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
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")
->Constructor()
->Constructor<const MaterialViewportSettings&>()
->Property("enableGrid", BehaviorValueProperty(&MaterialViewportSettings::m_enableGrid))
->Property("enableShadowCatcher", BehaviorValueProperty(&MaterialViewportSettings::m_enableShadowCatcher))
->Property("enableAlternateSkybox", BehaviorValueProperty(&MaterialViewportSettings::m_enableAlternateSkybox))
->Property("fieldOfView", BehaviorValueProperty(&MaterialViewportSettings::m_fieldOfView))
->Property("displayMapperOperationType", BehaviorValueProperty(&MaterialViewportSettings::m_displayMapperOperationType))
;
}
}
} // namespace MaterialEditor
@@ -38,7 +38,7 @@ namespace MaterialEditor
{
MaterialViewportWidget::MaterialViewportWidget(QWidget* parent)
: AtomToolsFramework::RenderViewportWidget(AzFramework::InvalidViewportId, parent)
: AtomToolsFramework::RenderViewportWidget(parent)
, m_ui(new Ui::MaterialViewportWidget)
{
m_ui->setupUi(this);
@@ -21,6 +21,8 @@
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/Document/MaterialDocumentSettings.h>
#include <QFileDialog>
namespace MaterialEditor
@@ -69,8 +71,11 @@ namespace MaterialEditor
QObject::connect(m_ui->m_materialTypeComboBox, static_cast<void (QComboBox::*)(const int)>(&QComboBox::currentIndexChanged), this, [this]() { UpdateMaterialTypeSelection(); });
QObject::connect(m_ui->m_materialTypeComboBox, &QComboBox::currentTextChanged, this, [this]() { UpdateMaterialTypeSelection(); });
// Select StandardPBR by default but we will later data drive this with editor settings
const int index = m_ui->m_materialTypeComboBox->findText("StandardPBR");
// Select the default material type from settings
auto settings =
AZ::UserSettings::CreateFind<MaterialDocumentSettings>(AZ::Crc32("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL);
const int index = m_ui->m_materialTypeComboBox->findText(settings->m_defaultMaterialTypeName.c_str());
if (index >= 0)
{
m_ui->m_materialTypeComboBox->setCurrentIndex(index);
@@ -5,4 +5,4 @@
<rect id="Icon-Background" x="0" y="0" width="24" height="24"></rect>
<path d="M11.9842667,6 C14.2018891,6 17.5404669,8 22,12 C17.5404669,16 14.2018891,18 11.9842667,18 C9.76664426,18 6.43855537,16 2,12 C6.43855537,8 9.76664426,6 11.9842667,6 Z M12,7.5 C9.51471863,7.5 7.5,9.51471863 7.5,12 C7.5,14.4852814 9.51471863,16.5 12,16.5 C14.4852814,16.5 16.5,14.4852814 16.5,12 C16.5,9.51471863 14.4852814,7.5 12,7.5 Z M12,9 C13.6568542,9 15,10.3431458 15,12 C15,13.6568542 13.6568542,15 12,15 C10.3431458,15 9,13.6568542 9,12 C9,10.3431458 10.3431458,9 12,9 Z" id="Combined-Shape" fill="#FFFFFF"></path>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 953 B

After

Width:  |  Height:  |  Size: 954 B

@@ -6,4 +6,4 @@
<g id="Icons-/-Toolbar-/-Ground" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M2,19 L5,6 L19,6 L22,19 L2,19 Z M5,14.667 L4.462,17 L8.051,17 L8.255,15 L5,15 L5,14.667 Z M19,14.667 L19,15 L15.699,15 L15.9,17 L19.538,17 L19,14.667 Z M13.699,15 L10.255,15 L10.051,17 L13.9,17 L13.699,15 Z M5.269,13.5 L8.407,13.5 L8.611,11.5 L5.731,11.5 L5.269,13.5 Z M18.269,11.5 L15.348,11.5 L15.549,13.5 L18.731,13.5 L18.269,11.5 Z M13.348,11.5 L10.611,11.5 L10.407,13.5 L13.549,13.5 L13.348,11.5 Z M6.077,10 L8.763,10 L8.967,8 L6.538,8 L6.077,10 Z M17.462,8 L10.967,8 L10.763,10 L13.198,10 L13,8.02631406 L15,8.02631406 L15.198,10 L17.923,10 L17.462,8 Z" id="Combined-Shape" fill="#FFFFFF"></path>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -7,4 +7,4 @@
<rect id="Rectangle" fill="#EEEEEE" fill-rule="nonzero" x="16" y="15.9999948" width="6" height="6"></rect>
<path d="M13.2003238,2.05728467 L13.3206336,2.08541409 C17.9843907,2.69389766 21.611637,6.4842271 21.9707625,11.2247926 C21.9900321,11.3980031 22,11.5711198 22,11.7433304 L21.997,11.815 L22,12 C22,12.6856005 21.9319119,13.3545263 21.802092,14.0004211 L14,14 L14.0004211,21.802092 C13.4430737,21.9141145 12.8685772,21.980171 12.2810157,21.9961774 L12,22 C6.45454545,22 2,17.5454545 2,12 C2,6.45454545 6.45454545,2 12,2 C12.1802332,2 12.359314,2.00470542 12.537127,2.01400079 C12.719362,1.98546889 12.9435559,2.00149401 13.2003238,2.05728467 Z M11.999,15.636 L9.54545455,15.6363636 C10.0721003,18.3573668 11.1072317,20.0613988 11.9144212,20.1756828 L11.999,20.181 L11.999,15.636 Z M7.72727273,15.6363636 L4.63636364,15.6363636 C5.54545455,17.4545455 7.09090909,18.8181818 8.90909091,19.6363636 C8.36363636,18.5454545 8,17.0909091 7.72727273,15.6363636 Z M11.999,10.181 L9.36363636,10.1818182 C9.27272727,10.7272727 9.27272727,11.3636364 9.27272727,12 C9.27272727,12.5090909 9.27272727,13.0181818 9.31927273,13.4807273 L9.36363636,13.8181818 L11.999,13.818 L11.999,10.181 Z M7.45454545,10.1818182 L4,10.1818182 C3.90909091,10.7272727 3.81818182,11.3636364 3.81818182,12 C3.81818182,12.5090909 3.87636364,13.0181818 3.94618182,13.4807273 L4,13.8181818 L7.54545455,13.8181818 C7.47272727,13.3090909 7.45818182,12.8581818 7.45527273,12.3723636 L7.45454545,12 L7.45454545,10.1818182 Z M11.9990157,3.81818265 C11.2091528,3.8195194 10.1655566,5.42953176 9.60376892,8.07613162 L9.54545455,8.36363636 L11.999,8.363 L11.9990157,3.81818265 Z M9,4.36363636 C7.1969697,5.13636364 5.71829405,6.3956229 4.79372428,8.0648304 L4.63636364,8.36363636 L7.72727273,8.36363636 C8,6.90909091 8.45454545,5.45454545 9,4.36363636 Z" id="Combined-Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="256px" height="256px" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icons / Application Icons / Material Editor</title>
<defs>
<polygon id="path-1" points="7.67007885e-15 0 256 0 256 256.000195 7.67007885e-15 256.000195"></polygon>
</defs>
<g id="Icons-/-Application-Icons-/-Material-Editor" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group" transform="translate(-0.000000, 0.000000)">
<g id="Fill-1-Clipped" transform="translate(-0.000000, 0.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="path-1"></g>
<path d="M184.641349,-0.000129743592 L71.3589754,-0.000129743592 C32.1115389,-0.000129743592 7.67007885e-15,32.1114092 7.67007885e-15,71.3588457 L7.67007885e-15,184.641219 C7.67007885e-15,223.888656 32.1115389,256.000195 71.3589754,256.000195 L184.641349,256.000195 C223.888785,256.000195 256.000324,223.888656 256.000324,184.641219 L256.000324,71.3588457 C256.000324,32.1114092 223.888785,-0.000129743592 184.641349,-0.000129743592" id="Fill-1" fill="#1E70EB" fill-rule="nonzero" mask="url(#mask-2)"></path>
</g>
<path d="M128.000162,32.2473156 C74.9006511,32.2473156 32.2467966,74.9005214 32.2467966,128.000681 C32.2467966,181.099543 74.9006511,223.752749 128.000162,223.752749 C181.099673,223.752749 223.752879,181.099543 223.752879,128.000681 C223.752879,74.9005214 181.099673,32.2473156 128.000162,32.2473156 L128.000162,32.2473156 Z M198.508668,93.1813935 L168.912209,93.1813935 C166.301119,79.2534189 162.81945,65.3254443 157.595973,54.8797877 C175.005617,62.7143545 189.804171,75.7717496 198.508668,93.1813935 L198.508668,93.1813935 Z M154.114304,128.000681 C154.114304,134.09344 154.114304,140.186848 153.243724,145.409676 L102.755952,145.409676 C101.885372,140.186848 101.885372,134.09344 101.885372,128.000681 C101.885372,121.906625 101.885372,115.813217 102.755952,110.590389 L153.243724,110.590389 C154.114304,115.813217 154.114304,121.906625 154.114304,128.000681 L154.114304,128.000681 Z M128.000162,206.343105 C120.165595,206.343105 109.719939,189.804041 104.497111,162.81932 L150.632634,162.81932 C146.280386,189.804041 135.83408,206.343105 128.000162,206.343105 L128.000162,206.343105 Z M104.497111,93.1813935 C109.719939,66.1960238 120.165595,49.6569595 128.000162,49.6569595 C135.83408,49.6569595 146.280386,66.1960238 151.502565,93.1813935 L104.497111,93.1813935 Z M99.2742823,54.8797877 C94.0508053,65.3254443 89.6985565,79.2534189 87.0874667,93.1813935 L57.4910073,93.1813935 C66.1961536,75.7717496 80.9940589,62.7143545 99.2742823,54.8797877 L99.2742823,54.8797877 Z M51.3975995,110.590389 L84.4757282,110.590389 L84.4757282,128.000681 C84.4757282,134.09344 84.4757282,139.316269 85.3463077,145.409676 L51.3975995,145.409676 C50.52702,140.186848 49.6564405,134.09344 49.6564405,128.000681 C49.6564405,121.906625 50.52702,115.813217 51.3975995,110.590389 L51.3975995,110.590389 Z M57.4910073,162.81932 L87.0874667,162.81932 C89.6985565,176.746646 93.1808745,190.674621 98.4037028,201.120277 C80.9940589,193.28571 66.1961536,180.228964 57.4910073,162.81932 L57.4910073,162.81932 Z M156.725393,201.120277 C161.948222,190.674621 166.301119,177.617874 168.042278,162.81932 L197.638089,162.81932 C189.804171,180.228964 175.005617,193.28571 156.725393,201.120277 L156.725393,201.120277 Z M204.602076,145.409676 L171.523947,145.409676 C172.394527,139.316269 172.394527,134.09344 172.394527,128.000681 C172.394527,121.906625 172.394527,116.683796 171.523947,110.590389 L204.602076,110.590389 C205.472656,115.813217 206.343235,121.906625 206.343235,128.000681 C206.343235,134.09344 205.472656,140.186848 204.602076,145.409676 L204.602076,145.409676 Z" id="Fill-4" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M128.000162,212.590259 L128.000162,125.542689 L128.000162,38.4944696 C128.000162,12.3803281 223.752879,73.3137573 223.752879,125.542689 C223.752879,177.770972 128.000162,238.705049 128.000162,212.590259" id="Fill-6" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

@@ -9,4 +9,4 @@
</g>
<path d="M22,20.8342395 C22,18.1069667 22,17.2661779 22,11.7433304 C22,6.22048287 22,5.379694 22,2.65242127 C22,-0.0748514543 12,6.28878491 12,11.7433304 C12,17.1978758 22,23.5615122 22,20.8342395 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero" transform="translate(17.000000, 11.743330) scale(-1, 1) translate(-17.000000, -11.743330) "></path>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

@@ -7,4 +7,4 @@
<path d="M10.25,0 C4.56590909,0 0,4.45454545 0,10 C0,15.5454545 4.56590909,20 10.25,20 C15.9340909,20 20.5,15.5454545 20.5,10 C20.5,4.45454545 15.9340909,0 10.25,0 Z M17.7977273,6.36363636 L14.6295455,6.36363636 C14.35,4.90909091 13.9772727,3.45454545 13.4181818,2.36363636 C15.2818182,3.18181818 16.8659091,4.54545455 17.7977273,6.36363636 Z M13.0454545,10 C13.0454545,10.6363636 13.0454545,11.2727273 12.9522727,11.8181818 L7.54772727,11.8181818 C7.45454545,11.2727273 7.45454545,10.6363636 7.45454545,10 C7.45454545,9.36363636 7.45454545,8.72727273 7.54772727,8.18181818 L12.9522727,8.18181818 C13.0454545,8.72727273 13.0454545,9.36363636 13.0454545,10 Z M10.25,18.1818182 C9.41136364,18.1818182 8.29318182,16.4545455 7.73409091,13.6363636 L12.6727273,13.6363636 C12.2068182,16.4545455 11.0886364,18.1818182 10.25,18.1818182 Z M7.73409091,6.36363636 C8.29318182,3.54545455 9.41136364,1.81818182 10.25,1.81818182 C11.0886364,1.81818182 12.2068182,3.54545455 12.7659091,6.36363636 L7.73409091,6.36363636 Z M7.175,2.36363636 C6.61590909,3.45454545 6.15,4.90909091 5.87045455,6.36363636 L2.70227273,6.36363636 C3.63409091,4.54545455 5.21818182,3.18181818 7.175,2.36363636 Z M2.05,8.18181818 L5.59090909,8.18181818 C5.59090909,8.81818182 5.59090909,9.36363636 5.59090909,10 C5.59090909,10.6363636 5.59090909,11.1818182 5.68409091,11.8181818 L2.05,11.8181818 C1.95681818,11.2727273 1.86363636,10.6363636 1.86363636,10 C1.86363636,9.36363636 1.95681818,8.72727273 2.05,8.18181818 Z M2.70227273,13.6363636 L5.87045455,13.6363636 C6.15,15.0909091 6.52272727,16.5454545 7.08181818,17.6363636 C5.21818182,16.8181818 3.63409091,15.4545455 2.70227273,13.6363636 Z M13.325,17.6363636 C13.8840909,16.5454545 14.35,15.1818182 14.5363636,13.6363636 L17.7045455,13.6363636 C16.8659091,15.4545455 15.2818182,16.8181818 13.325,17.6363636 Z M18.45,11.8181818 L14.9090909,11.8181818 C15.0022727,11.1818182 15.0022727,10.6363636 15.0022727,10 C15.0022727,9.36363636 15.0022727,8.81818182 14.9090909,8.18181818 L18.45,8.18181818 C18.5431818,8.72727273 18.6363636,9.36363636 18.6363636,10 C18.6363636,10.6363636 18.5431818,11.2727273 18.45,11.8181818 Z" id="Shape"></path>
</g>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -6,4 +6,4 @@
<g id="Icons-/-Toolbar-/-Shadow" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M6.99979618,18.810136 L9.18779618,20.999136 L7,21 L6.99979618,18.810136 Z M17,3 L17,7.312 L20.9997962,11.310136 L20.9997962,13.189136 L17,9.19 L17,11.311 L20.9997962,15.310136 L20.9997962,17.689136 L17,13.69 L17,15.812 L20.9997962,19.811136 L21,21 L19.8097962,20.999136 L15.81,17 L13.689,17 L17.6887962,20.999136 L15.3097962,20.999136 L11.31,17 L9.188,17 L13.1877962,20.999136 L11.3097962,20.999136 L7.311,17 L3,17 L3,3 L17,3 Z M21,7 L20.9997962,9.18913601 L18.8087962,6.99913601 L21,7 Z" id="Combined-Shape" fill="#FFFFFF"></path>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 1023 B

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -7,4 +7,4 @@
<path d="M14.550959,11.6 L12,8.6 L11,9.6 L8,6.6 L3.46109347,11.6 L3.46109347,14.5401062 L14.550959,14.5401062 L14.550959,11.6 Z M13.5,3 C14.3284271,3 15,3.67157288 15,4.5 C15,5.32842712 14.3284271,6 13.5,6 C12.6715729,6 12,5.32842712 12,4.5 C12,3.67157288 12.6715729,3 13.5,3 Z M0,1.77635684e-15 L0,18 L18,18 L18,1.77635684e-15 L0,1.77635684e-15 Z M16,16 L2,16 L2,2 L16,2 L16,16 Z" id="Shape"></path>
</g>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 946 B

After

Width:  |  Height:  |  Size: 947 B

@@ -11,4 +11,4 @@
<rect id="Rectangle" fill="#FFFFFF" x="5" y="3" width="16" height="2"></rect>
<rect id="Rectangle" fill="#FFFFFF" x="19" y="3" width="2" height="16"></rect>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

@@ -110,30 +110,19 @@ namespace MaterialEditor
{
using namespace AzToolsFramework::AssetBrowser;
// Material Browser uses the following filters:
// 1. [All source files (no products) that contain products matching the assetType specified by searchWidget (default is materials and textures)]
// 2. [All folders (including empty folders)]
// 3. [All Sources and folders matching the search text typed in search widget]
// Final filter = ((1 OR 2) AND 3)
QSharedPointer<EntryTypeFilter> sourceFilter(new EntryTypeFilter);
sourceFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Source);
QSharedPointer<CompositeFilter> assetTypeFilter(new CompositeFilter(CompositeFilter::LogicOperatorType::AND));
assetTypeFilter->AddFilter(sourceFilter);
assetTypeFilter->AddFilter(m_ui->m_searchWidget->GetTypesFilter());
QSharedPointer<EntryTypeFilter> folderFilter(new EntryTypeFilter);
folderFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Folder);
QSharedPointer<CompositeFilter> sourceOrFolderFilter(new CompositeFilter(CompositeFilter::LogicOperatorType::OR));
sourceOrFolderFilter->AddFilter(assetTypeFilter);
sourceOrFolderFilter->AddFilter(sourceFilter);
sourceOrFolderFilter->AddFilter(folderFilter);
QSharedPointer<CompositeFilter> finalFilter(new CompositeFilter(CompositeFilter::LogicOperatorType::AND));
finalFilter->AddFilter(sourceOrFolderFilter);
finalFilter->AddFilter(m_ui->m_searchWidget->GetStringFilter());
finalFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down);
finalFilter->AddFilter(m_ui->m_searchWidget->GetFilter());
return finalFilter;
}
@@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/">
<file>MaterialEditor.qss</file>
<file>Icons/materialeditor.svg</file>
<file>Icons/material.svg</file>
<file>Icons/materialtype.svg</file>
<file>Icons/mesh.svg</file>
@@ -15,4 +15,4 @@ AzToolsFramework--PropertyRowWidget[IsOverridden=true] QLabel
{
font-weight: bold;
color: #F5A623;
}
}
@@ -31,6 +31,7 @@
#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>
@@ -248,6 +249,24 @@ namespace MaterialEditor
}
}
});
menu->addSeparator();
QAction* createMaterialAction = menu->addAction(QObject::tr("Create Material..."));
QObject::connect(createMaterialAction, &QAction::triggered, caller, [caller, entry]()
{
CreateMaterialDialog createDialog(entry->GetFullPath().c_str(), caller);
createDialog.adjustSize();
if (createDialog.exec() == QDialog::Accepted &&
!createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() &&
!createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty())
{
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile,
createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData(),
createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData());
}
});
}
void MaterialEditorBrowserInteractions::AddPerforceMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
@@ -10,45 +10,51 @@
*
*/
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzFramework/Application/Application.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
#include <AzQtComponents/Components/StyleManager.h>
#include <AzQtComponents/Utilities/QtPluginPaths.h>
#include <AtomToolsFramework/Util/Util.h>
#include <Atom/Document/MaterialDocumentRequestBus.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/Window/MaterialEditorWindowNotificationBus.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Common/JsonUtils.h>
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
#include <Atom/Document/MaterialDocumentRequestBus.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/Window/MaterialEditorWindowNotificationBus.h>
#include <Atom/Window/MaterialEditorWindowSettings.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzFramework/Application/Application.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzQtComponents/Components/StyleManager.h>
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
#include <AzQtComponents/Utilities/QtPluginPaths.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
#include <Viewport/MaterialViewportWidget.h>
#include <Viewport/MaterialViewportWidget.h>
#include <Window/MaterialEditorWindow.h>
#include <Window/PerformanceMonitor/PerformanceMonitorWidget.h>
#include <Window/HelpDialog/HelpDialog.h>
#include <Window/MaterialBrowserWidget.h>
#include <Window/MaterialInspector/MaterialInspector.h>
#include <Window/ViewportSettingsInspector/ViewportSettingsInspector.h>
#include <Window/CreateMaterialDialog/CreateMaterialDialog.h>
#include <Window/HelpDialog/HelpDialog.h>
#include <Window/SettingsDialog/SettingsDialog.h>
#include <Window/MaterialBrowserWidget.h>
#include <Window/MaterialEditorWindow.h>
#include <Window/MaterialInspector/MaterialInspector.h>
#include <Window/PerformanceMonitor/PerformanceMonitorWidget.h>
#include <Window/ViewportSettingsInspector/ViewportSettingsInspector.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QApplication>
#include <QByteArray>
#include <QCloseEvent>
#include <QVariant>
#include <QDesktopWidget>
#include <QFileDialog>
#include <QWindow>
#include <QVBoxLayout>
#include <QVariant>
#include <QWindow>
AZ_POP_DISABLE_WARNING
namespace MaterialEditor
@@ -56,9 +62,18 @@ namespace MaterialEditor
MaterialEditorWindow::MaterialEditorWindow(QWidget* parent /* = 0 */)
: AzQtComponents::DockMainWindow(parent)
{
resize(1280, 1024);
// Among other things, we need the window wrapper to save the main window size, position, and state
auto mainWindowWrapper =
new AzQtComponents::WindowDecorationWrapper(AzQtComponents::WindowDecorationWrapper::OptionAutoTitleBarButtons);
mainWindowWrapper->setGuest(this);
mainWindowWrapper->enableSaveRestoreGeometry("amazon", "MaterialEditor", "mainWindowGeometry");
// set the style sheet for RPE highlighting and other styling
AzQtComponents::StyleManager::setStyleSheet(this, QStringLiteral(":/MaterialEditor.qss"));
QApplication::setWindowIcon(QIcon(":/Icons/materialtype.svg"));
QApplication::setWindowIcon(QIcon(":/Icons/materialeditor.svg"));
AZ::Name apiName = AZ::RHI::Factory::Get().GetName();
if (!apiName.IsEmpty())
@@ -74,6 +89,7 @@ namespace MaterialEditor
m_advancedDockManager = new AzQtComponents::FancyDocking(this);
setObjectName("MaterialEditorWindow");
setDockNestingEnabled(true);
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
@@ -81,17 +97,21 @@ namespace MaterialEditor
setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
m_menuBar = new QMenuBar(this);
m_menuBar->setObjectName("MenuBar");
setMenuBar(m_menuBar);
m_toolBar = new MaterialEditorToolBar(this);
m_toolBar->setObjectName("ToolBar");
addToolBar(m_toolBar);
m_centralWidget = new QWidget(this);
m_tabWidget = new AzQtComponents::TabWidget(m_centralWidget);
m_tabWidget->setObjectName("TabWidget");
m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
m_tabWidget->setContentsMargins(0, 0, 0, 0);
m_materialViewport = new MaterialViewportWidget(m_centralWidget);
m_materialViewport->setObjectName("Viewport");
m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
QVBoxLayout* vl = new QVBoxLayout(m_centralWidget);
@@ -103,7 +123,8 @@ namespace MaterialEditor
setCentralWidget(m_centralWidget);
m_statusBar = new StatusBarWidget(this);
this->statusBar()->addPermanentWidget(m_statusBar, 1);
m_statusBar->setObjectName("StatusBar");
statusBar()->addPermanentWidget(m_statusBar, 1);
SetupMenu();
SetupTabs();
@@ -118,6 +139,19 @@ namespace MaterialEditor
SetDockWidgetVisible("Performance Monitor", false);
SetDockWidgetVisible("Python Terminal", false);
// Restore geometry and show the window
mainWindowWrapper->showFromSettings();
// Restore additional state for docked windows
auto windowSettings = AZ::UserSettings::CreateFind<MaterialEditorWindowSettings>(
AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL);
if (!windowSettings->m_mainWindowState.empty())
{
QByteArray windowState(windowSettings->m_mainWindowState.data(), windowSettings->m_mainWindowState.size());
m_advancedDockManager->restoreState(windowState);
}
MaterialEditorWindowRequestBus::Handler::BusConnect();
MaterialDocumentNotificationBus::Handler::BusConnect();
OnDocumentOpened(AZ::Uuid::CreateNull());
@@ -129,6 +163,12 @@ namespace MaterialEditor
MaterialEditorWindowRequestBus::Handler::BusDisconnect();
}
void MaterialEditorWindow::ActivateWindow()
{
activateWindow();
raise();
}
bool MaterialEditorWindow::AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation)
{
auto dockWidgetItr = m_dockWidgets.find(name);
@@ -138,8 +178,9 @@ namespace MaterialEditor
}
auto dockWidget = new AzQtComponents::StyledDockWidget(name.c_str());
dockWidget->setObjectName(name.c_str());
dockWidget->setObjectName(QString("%1_DockWidget").arg(name.c_str()));
dockWidget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
widget->setObjectName(name.c_str());
widget->setParent(dockWidget);
widget->setMinimumSize(QSize(300, 300));
dockWidget->setWidget(widget);
@@ -197,15 +238,16 @@ namespace MaterialEditor
QSize requestedWindowSize = size() + offset;
resize(requestedWindowSize);
AZ_Assert(m_materialViewport->size() == requestedViewportSize,
AZ_Assert(
m_materialViewport->size() == requestedViewportSize,
"Resizing the window did not give the expected viewport size. Requested %d x %d but got %d x %d.",
requestedViewportSize.width(), requestedViewportSize.height(),
m_materialViewport->size().width(), m_materialViewport->size().height());
requestedViewportSize.width(), requestedViewportSize.height(), m_materialViewport->size().width(),
m_materialViewport->size().height());
QSize newDeviceSize = m_materialViewport->size();
AZ_Warning("Material Editor", newDeviceSize.width() == width && newDeviceSize.height() == height,
"Resizing the window did not give the expected frame size. Requested %d x %d but got %d x %d.",
width, height,
AZ_Warning(
"Material Editor", newDeviceSize.width() == width && newDeviceSize.height() == height,
"Resizing the window did not give the expected frame size. Requested %d x %d but got %d x %d.", width, height,
newDeviceSize.width(), newDeviceSize.height());
}
@@ -229,6 +271,13 @@ namespace MaterialEditor
return;
}
// Capture docking state before shutdown
auto windowSettings = AZ::UserSettings::CreateFind<MaterialEditorWindowSettings>(
AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL);
QByteArray windowState = m_advancedDockManager->saveState();
windowSettings->m_mainWindowState.assign(windowState.begin(), windowState.end());
MaterialEditorWindowNotificationBus::Broadcast(&MaterialEditorWindowNotifications::OnMaterialEditorWindowClosing);
}
@@ -266,7 +315,7 @@ namespace MaterialEditor
m_actionUndo->setEnabled(canUndo);
m_actionRedo->setEnabled(canRedo);
m_actionPreferences->setEnabled(false);
m_actionSettings->setEnabled(true);
m_actionAssetBrowser->setEnabled(true);
m_actionInspector->setEnabled(true);
@@ -459,9 +508,11 @@ namespace MaterialEditor
m_menuEdit->addSeparator();
m_actionPreferences = m_menuEdit->addAction("&Preferences...", [this]() {
m_actionSettings = m_menuEdit->addAction("&Settings...", [this]() {
SettingsDialog dialog(this);
dialog.exec();
}, QKeySequence::Preferences);
m_actionPreferences->setEnabled(false);
m_actionSettings->setEnabled(true);
m_menuView = m_menuBar->addMenu("&View");
@@ -506,8 +557,8 @@ namespace MaterialEditor
m_menuHelp = m_menuBar->addMenu("&Help");
m_actionHelp = m_menuHelp->addAction("&Help...", [this]() {
HelpDialog dlg(this);
dlg.exec();
HelpDialog dialog(this);
dialog.exec();
});
m_actionAbout = m_menuHelp->addAction("&About...", [this]() {
@@ -61,6 +61,7 @@ namespace MaterialEditor
private:
// MaterialEditorWindowRequestBus::Handler overrides...
void ActivateWindow() override;
bool AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation) override;
void RemoveDockWidget(const AZStd::string& name) override;
void SetDockWidgetVisible(const AZStd::string& name, bool visible) override;
@@ -118,7 +119,7 @@ namespace MaterialEditor
QMenu* m_menuEdit = {};
QAction* m_actionUndo = {};
QAction* m_actionRedo = {};
QAction* m_actionPreferences = {};
QAction* m_actionSettings = {};
QMenu* m_menuView = {};
QAction* m_actionAssetBrowser = {};
@@ -10,25 +10,24 @@
*
*/
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <Atom/Window/MaterialEditorWindowFactoryRequestBus.h>
#include <Atom/Window/MaterialEditorWindowSettings.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzToolsFramework/API/ViewPaneOptions.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/API/ViewPaneOptions.h>
#include <AzToolsFramework/UI/UICore/QWidgetSavedState.h>
#include <Atom/Window/MaterialEditorWindowFactoryRequestBus.h>
#include <Source/Window/MaterialEditorWindowComponent.h>
#include <Source/Window/MaterialEditorWindow.h>
#include <Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h>
#include <Window/MaterialEditorWindow.h>
#include <Window/MaterialEditorWindowComponent.h>
#include <Window/ViewportSettingsInspector/ViewportSettingsInspector.h>
namespace MaterialEditor
{
void MaterialEditorWindowComponent::Reflect(AZ::ReflectContext* context)
{
GeneralViewportSettings::Reflect(context);
MaterialEditorWindowSettings::Reflect(context);
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
@@ -50,6 +49,7 @@ namespace MaterialEditor
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "materialeditor")
->Event("ActivateWindow", &MaterialEditorWindowRequestBus::Events::ActivateWindow)
->Event("SetDockWidgetVisible", &MaterialEditorWindowRequestBus::Events::SetDockWidgetVisible)
->Event("IsDockWidgetVisible", &MaterialEditorWindowRequestBus::Events::IsDockWidgetVisible)
->Event("GetDockWidgetNames", &MaterialEditorWindowRequestBus::Events::GetDockWidgetNames)
@@ -101,7 +101,6 @@ namespace MaterialEditor
m_materialEditorBrowserInteractions.reset(aznew MaterialEditorBrowserInteractions);
m_window.reset(aznew MaterialEditorWindow);
m_window->show();
}
void MaterialEditorWindowComponent::DestroyMaterialEditorWindow()
@@ -0,0 +1,50 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/Window/MaterialEditorWindowSettings.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
namespace MaterialEditor
{
void MaterialEditorWindowSettings::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<MaterialEditorWindowSettings, AZ::UserSettings>()
->Version(1)
->Field("mainWindowState", &MaterialEditorWindowSettings::m_mainWindowState)
->Field("inspectorCollapsedGroups", &MaterialEditorWindowSettings::m_inspectorCollapsedGroups)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<MaterialEditorWindowSettings>(
"MaterialEditorWindowSettings", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
;
}
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
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")
->Constructor()
->Constructor<const MaterialEditorWindowSettings&>()
;
}
}
} // namespace MaterialEditor
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Material/MaterialPropertyId.h>
@@ -21,13 +21,16 @@
#include <AtomToolsFramework/Inspector/InspectorPropertyGroupWidget.h>
#include <AtomToolsFramework/Util/MaterialPropertyUtil.h>
#include <Source/Window/MaterialInspector/MaterialInspector.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();
}
@@ -39,6 +42,7 @@ namespace MaterialEditor
void MaterialInspector::Reset()
{
m_documentPath.clear();
m_documentId = AZ::Uuid::CreateNull();
m_groups = {};
@@ -46,6 +50,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();
@@ -55,6 +75,8 @@ namespace MaterialEditor
bool isOpen = false;
MaterialDocumentRequestBus::EventResult(isOpen, m_documentId, &MaterialDocumentRequestBus::Events::IsOpen);
MaterialDocumentRequestBus::EventResult(m_documentPath, m_documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
if (!m_documentId.IsNull() && isOpen)
{
// Create the top group for displaying details about the material
@@ -70,10 +92,24 @@ 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;
MaterialDocumentRequestBus::EventResult(materialTypeSourceData, m_documentId, &MaterialDocumentRequestBus::Events::GetMaterialTypeSourceData);
MaterialDocumentRequestBus::EventResult(
materialTypeSourceData, m_documentId, &MaterialDocumentRequestBus::Events::GetMaterialTypeSourceData);
const AZStd::string groupNameId = "details";
const AZStd::string groupDisplayName = "Details";
@@ -81,20 +117,19 @@ namespace MaterialEditor
auto& group = m_groups[groupNameId];
AtomToolsFramework::DynamicProperty property;
MaterialDocumentRequestBus::EventResult(property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("details.materialType"));
MaterialDocumentRequestBus::EventResult(
property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("details.materialType"));
group.m_properties.push_back(property);
property = {};
MaterialDocumentRequestBus::EventResult(property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("details.parentMaterial"));
MaterialDocumentRequestBus::EventResult(
property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("details.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
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(&group, &group, group.TYPEINFO_Uuid(), this, this,
[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);
});
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
&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);
}
@@ -114,32 +149,33 @@ namespace MaterialEditor
for (const auto& uvNamePair : uvNameMap)
{
AtomToolsFramework::DynamicProperty property;
MaterialDocumentRequestBus::EventResult(property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::RPI::MaterialPropertyId(groupNameId, uvNamePair.m_shaderInput.ToString()).GetFullName());
MaterialDocumentRequestBus::EventResult(
property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty,
AZ::RPI::MaterialPropertyId(groupNameId, uvNamePair.m_shaderInput.ToString()).GetFullName());
group.m_properties.push_back(property);
property.SetValue(property.GetConfig().m_parentValue);
}
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(&group, &group, group.TYPEINFO_Uuid(), this, this,
[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);
});
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
&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);
}
void MaterialInspector::AddPropertiesGroup()
{
const AZ::RPI::MaterialTypeSourceData* materialTypeSourceData = nullptr;
MaterialDocumentRequestBus::EventResult(materialTypeSourceData, m_documentId, &MaterialDocumentRequestBus::Events::GetMaterialTypeSourceData);
MaterialDocumentRequestBus::EventResult(
materialTypeSourceData, m_documentId, &MaterialDocumentRequestBus::Events::GetMaterialTypeSourceData);
for (const auto& groupDefinition : materialTypeSourceData->GetGroupDefinitionsInDisplayOrder())
{
const AZStd::string& groupNameId = groupDefinition.m_nameId;
const AZStd::string& groupDisplayName = !groupDefinition.m_displayName.empty() ? groupDefinition.m_displayName : groupNameId;
const AZStd::string& groupDescription = !groupDefinition.m_description.empty() ? groupDefinition.m_description : groupDisplayName;
const AZStd::string& groupDescription =
!groupDefinition.m_description.empty() ? groupDefinition.m_description : groupDisplayName;
auto& group = m_groups[groupNameId];
const auto& propertyLayout = materialTypeSourceData->m_propertyLayout;
@@ -150,18 +186,17 @@ namespace MaterialEditor
for (const auto& propertyDefinition : propertyListItr->second)
{
AtomToolsFramework::DynamicProperty property;
MaterialDocumentRequestBus::EventResult(property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName());
MaterialDocumentRequestBus::EventResult(
property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty,
AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName());
group.m_properties.push_back(property);
}
}
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(&group, &group, group.TYPEINFO_Uuid(), this, this,
[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);
});
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
&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);
}
}
@@ -177,7 +212,8 @@ namespace MaterialEditor
if (!AtomToolsFramework::ArePropertyValuesEqual(reflectedProperty.GetValue(), property.GetValue()))
{
reflectedProperty.SetValue(property.GetValue());
AtomToolsFramework::InspectorRequestBus::Event(documentId, &AtomToolsFramework::InspectorRequestBus::Events::RefreshGroup, groupPair.first);
AtomToolsFramework::InspectorRequestBus::Event(
documentId, &AtomToolsFramework::InspectorRequestBus::Events::RefreshGroup, groupPair.first);
}
return;
}
@@ -185,7 +221,8 @@ namespace MaterialEditor
}
}
void MaterialInspector::OnDocumentPropertyConfigModified(const AZ::Uuid& documentId, const AtomToolsFramework::DynamicProperty& property)
void MaterialInspector::OnDocumentPropertyConfigModified(
const AZ::Uuid& documentId, const AtomToolsFramework::DynamicProperty& property)
{
for (auto& groupPair : m_groups)
{
@@ -197,12 +234,14 @@ namespace MaterialEditor
if (reflectedProperty.GetVisibility() != property.GetVisibility())
{
reflectedProperty.SetConfig(property.GetConfig());
AtomToolsFramework::InspectorRequestBus::Event(documentId, &AtomToolsFramework::InspectorRequestBus::Events::RebuildGroup, groupPair.first);
AtomToolsFramework::InspectorRequestBus::Event(
documentId, &AtomToolsFramework::InspectorRequestBus::Events::RebuildGroup, groupPair.first);
}
else
{
reflectedProperty.SetConfig(property.GetConfig());
AtomToolsFramework::InspectorRequestBus::Event(documentId, &AtomToolsFramework::InspectorRequestBus::Events::RefreshGroup, groupPair.first);
AtomToolsFramework::InspectorRequestBus::Event(
documentId, &AtomToolsFramework::InspectorRequestBus::Events::RefreshGroup, groupPair.first);
}
return;
}
@@ -214,7 +253,8 @@ namespace MaterialEditor
{
// For some reason the reflected property editor notifications are not symmetrical
// This function is called continuously anytime a property changes until the edit has completed
// Because of that, we have to track whether or not we are continuing to edit the same property to know when editing has started and ended
// Because of that, we have to track whether or not we are continuing to edit the same property to know when editing has started and
// ended
const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(pNode);
if (property)
{
@@ -233,23 +273,24 @@ namespace MaterialEditor
{
if (m_activeProperty == property)
{
MaterialDocumentRequestBus::Event(m_documentId, &MaterialDocumentRequestBus::Events::SetPropertyValue,
property->GetId(), property->GetValue());
MaterialDocumentRequestBus::Event(
m_documentId, &MaterialDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue());
}
}
}
void MaterialInspector::SetPropertyEditingComplete(AzToolsFramework::InstanceDataNode* pNode)
{
// As above, there are symmetrical functions on the notification interface for when editing begins and ends and has been completed but they are not being called following that pattern.
// when this function executes the changes to the property are ready to be committed or reverted
// As above, there are symmetrical functions on the notification interface for when editing begins and ends and has been completed
// but they are not being called following that pattern. when this function executes the changes to the property are ready to be
// committed or reverted
const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(pNode);
if (property)
{
if (m_activeProperty == property)
{
MaterialDocumentRequestBus::Event(m_documentId, &MaterialDocumentRequestBus::Events::SetPropertyValue,
property->GetId(), property->GetValue());
MaterialDocumentRequestBus::Event(
m_documentId, &MaterialDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue());
MaterialDocumentRequestBus::Event(m_documentId, &MaterialDocumentRequestBus::Events::EndEdit);
m_activeProperty = nullptr;
@@ -258,4 +299,4 @@ namespace MaterialEditor
}
} // namespace MaterialEditor
#include <Source/Window/MaterialInspector/moc_MaterialInspector.cpp>
#include <Window/MaterialInspector/moc_MaterialInspector.cpp>
@@ -20,6 +20,7 @@
#include <AtomToolsFramework/Inspector/InspectorWidget.h>
#include <Atom/Document/MaterialDocumentNotificationBus.h>
#include <Atom/Window/MaterialEditorWindowSettings.h>
#endif
namespace MaterialEditor
@@ -41,7 +42,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();
@@ -64,6 +74,8 @@ namespace MaterialEditor
const AtomToolsFramework::DynamicProperty* m_activeProperty = nullptr;
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
@@ -0,0 +1,43 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Window/SettingsDialog/SettingsDialog.h>
#include <Window/SettingsDialog/SettingsWidget.h>
#include <QDialogButtonBox>
#include <QVBoxLayout>
namespace MaterialEditor
{
SettingsDialog::SettingsDialog(QWidget* parent)
: QDialog(parent)
{
setWindowTitle("Material Editor Settings");
setFixedSize(600, 300);
setLayout(new QVBoxLayout(this));
auto settingsWidget = new SettingsWidget(this);
settingsWidget->Populate();
layout()->addWidget(settingsWidget);
// Create the bottom row of the dialog with action buttons
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok, this);
layout()->addWidget(buttonBox);
QObject::connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
QObject::connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
setModal(true);
}
} // namespace MaterialEditor
//#include <Window/SettingsDialog/moc_SettingsDialog.cpp>
@@ -0,0 +1,27 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <QDialog>
namespace MaterialEditor
{
class SettingsDialog
: public QDialog
{
Q_OBJECT
public:
SettingsDialog(QWidget* parent = nullptr);
~SettingsDialog() = default;
};
} // namespace MaterialEditor
@@ -0,0 +1,72 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Window/SettingsDialog/SettingsWidget.h>
#include <AtomToolsFramework/Inspector/InspectorPropertyGroupWidget.h>
namespace MaterialEditor
{
SettingsWidget::SettingsWidget(QWidget* parent)
: AtomToolsFramework::InspectorWidget(parent)
{
m_documentSettings =
AZ::UserSettings::CreateFind<MaterialDocumentSettings>(AZ::Crc32("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL);
}
SettingsWidget::~SettingsWidget()
{
AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect();
}
void SettingsWidget::Populate()
{
AddGroupsBegin();
AddDocumentGroup();
AddGroupsEnd();
}
void SettingsWidget::AddDocumentGroup()
{
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"));
AddGroup(
groupNameId, groupDisplayName, groupDescription,
new AtomToolsFramework::InspectorPropertyGroupWidget(
m_documentSettings.get(), nullptr, m_documentSettings->TYPEINFO_Uuid(), this, this, saveStateKey));
}
void SettingsWidget::Reset()
{
AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect();
AtomToolsFramework::InspectorWidget::Reset();
}
void SettingsWidget::BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode)
{
AZ_UNUSED(pNode);
}
void SettingsWidget::AfterPropertyModified(AzToolsFramework::InstanceDataNode* pNode)
{
AZ_UNUSED(pNode);
}
void SettingsWidget::SetPropertyEditingComplete(AzToolsFramework::InstanceDataNode* pNode)
{
AZ_UNUSED(pNode);
}
} // namespace MaterialEditor
//#include <Window/SettingsWidget/moc_SettingsWidget.cpp>
@@ -0,0 +1,54 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <Atom/Document/MaterialDocumentSettings.h>
#include <AtomToolsFramework/Inspector/InspectorWidget.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h>
#endif
namespace MaterialEditor
{
//! Provides controls for viewing and editing settings.
class SettingsWidget
: public AtomToolsFramework::InspectorWidget
, private AzToolsFramework::IPropertyEditorNotify
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(SettingsWidget, AZ::SystemAllocator, 0);
explicit SettingsWidget(QWidget* parent = nullptr);
~SettingsWidget() override;
void Populate();
private:
void AddDocumentGroup();
// AtomToolsFramework::InspectorRequestBus::Handler overrides...
void Reset() override;
// AzToolsFramework::IPropertyEditorNotify overrides...
void BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode) override;
void AfterPropertyModified(AzToolsFramework::InstanceDataNode* pNode) override;
void SetPropertyEditingActive([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode) override {}
void SetPropertyEditingComplete(AzToolsFramework::InstanceDataNode* pNode) override;
void SealUndoStack() override {}
void RequestPropertyContextMenu(AzToolsFramework::InstanceDataNode*, const QPoint&) override {}
void PropertySelectionChanged(AzToolsFramework::InstanceDataNode*, bool) override {}
AZStd::intrusive_ptr<MaterialDocumentSettings> m_documentSettings;
};
} // namespace MaterialEditor
@@ -10,13 +10,13 @@
*
*/
#include <Atom/Document/MaterialEditorSettingsBus.h>
#include <Atom/Viewport/MaterialViewportNotificationBus.h>
#include <Atom/Viewport/MaterialViewportRequestBus.h>
#include <Atom/Viewport/MaterialViewportSettings.h>
#include <AzCore/std/containers/vector.h>
#include <Source/Window/ToolBar/LightingPresetComboBox.h>
#include <Source/Window/ToolBar/MaterialEditorToolBar.h>
#include <Source/Window/ToolBar/ModelPresetComboBox.h>
#include <Window/ToolBar/LightingPresetComboBox.h>
#include <Window/ToolBar/MaterialEditorToolBar.h>
#include <Window/ToolBar/ModelPresetComboBox.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <AzQtComponents/Components/Widgets/ToolBar.h>
@@ -33,15 +33,16 @@ namespace MaterialEditor
{
AzQtComponents::ToolBar::addMainToolBarStyle(this);
AZStd::intrusive_ptr<MaterialViewportSettings> viewportSettings =
AZ::UserSettings::CreateFind<MaterialViewportSettings>(AZ::Crc32("MaterialViewportSettings"), AZ::UserSettings::CT_GLOBAL);
// Add toggle grid button
m_toggleGrid = addAction(QIcon(":/Icons/grid.svg"), "Toggle Grid");
m_toggleGrid->setCheckable(true);
connect(m_toggleGrid, &QAction::triggered, [this]() {
MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Events::SetGridEnabled, m_toggleGrid->isChecked());
});
bool enableGrid = false;
MaterialViewportRequestBus::BroadcastResult(enableGrid, &MaterialViewportRequestBus::Events::GetGridEnabled);
m_toggleGrid->setChecked(enableGrid);
m_toggleGrid->setChecked(viewportSettings->m_enableGrid);
// Add toggle shadow catcher button
m_toggleShadowCatcher = addAction(QIcon(":/Icons/shadow.svg"), "Toggle Shadow Catcher");
@@ -50,30 +51,36 @@ namespace MaterialEditor
MaterialViewportRequestBus::Broadcast(
&MaterialViewportRequestBus::Events::SetShadowCatcherEnabled, m_toggleShadowCatcher->isChecked());
});
bool enableShadowCatcher = false;
MaterialViewportRequestBus::BroadcastResult(enableShadowCatcher, &MaterialViewportRequestBus::Events::GetShadowCatcherEnabled);
m_toggleShadowCatcher->setChecked(enableShadowCatcher);
m_toggleShadowCatcher->setChecked(viewportSettings->m_enableShadowCatcher);
// Add mapping selection button
//[GFX TODO][ATOM-3992]
QToolButton* toneMappingButton = new QToolButton(this);
QMenu* toneMappingMenu = new QMenu(toneMappingButton);
toneMappingMenu->addAction("None", [this]() {
MaterialEditorSettingsRequestBus::Broadcast(&MaterialEditorSettingsRequests::SetStringProperty, "toneMapping", "None");
});
toneMappingMenu->addAction("Gamma2.2", [this]() {
MaterialEditorSettingsRequestBus::Broadcast(&MaterialEditorSettingsRequests::SetStringProperty, "toneMapping", "Gamma2.2");
});
toneMappingMenu->addAction("ACES", [this]() {
MaterialEditorSettingsRequestBus::Broadcast(&MaterialEditorSettingsRequests::SetStringProperty, "toneMapping", "ACES");
});
m_operationNames = {
{AZ::Render::DisplayMapperOperationType::Reinhard, "Reinhard"},
{AZ::Render::DisplayMapperOperationType::GammaSRGB, "GammaSRGB"},
{AZ::Render::DisplayMapperOperationType::Passthrough, "Passthrough"},
{AZ::Render::DisplayMapperOperationType::AcesLut, "AcesLut"},
{AZ::Render::DisplayMapperOperationType::Aces, "Aces"}};
for (auto operationNamePair : m_operationNames)
{
m_operationActions[operationNamePair.first] = toneMappingMenu->addAction(operationNamePair.second, [operationNamePair]() {
MaterialViewportRequestBus::Broadcast(
&MaterialViewportRequestBus::Events::SetDisplayMapperOperationType, operationNamePair.first);
});
m_operationActions[operationNamePair.first]->setCheckable(true);
m_operationActions[operationNamePair.first]->setChecked(
operationNamePair.first == viewportSettings->m_displayMapperOperationType);
}
toneMappingButton->setMenu(toneMappingMenu);
toneMappingButton->setText("Tone Mapping");
toneMappingButton->setIcon(QIcon(":/Icons/toneMapping.svg"));
toneMappingButton->setPopupMode(QToolButton::InstantPopup);
// hiding button until DisplayMapper supports changing settings at run time
toneMappingButton->setVisible(false);
toneMappingButton->setVisible(true);
addWidget(toneMappingButton);
// Add model combo box
@@ -99,6 +106,14 @@ namespace MaterialEditor
m_toggleGrid->setChecked(enable);
}
void MaterialEditorToolBar::OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType)
{
for (auto operationActionPair : m_operationActions)
{
operationActionPair.second->setChecked(operationActionPair.first == operationType);
}
}
void MaterialEditorToolBar::OnShadowCatcherEnabledChanged(bool enable)
{
m_toggleShadowCatcher->setChecked(enable);
@@ -106,4 +121,4 @@ namespace MaterialEditor
} // namespace MaterialEditor
#include <Source/Window/ToolBar/moc_MaterialEditorToolBar.cpp>
#include <Window/ToolBar/moc_MaterialEditorToolBar.cpp>
@@ -33,8 +33,12 @@ namespace MaterialEditor
// MaterialViewportNotificationBus::Handler overrides...
void OnShadowCatcherEnabledChanged([[maybe_unused]] bool enable) override;
void OnGridEnabledChanged([[maybe_unused]] bool enable) override;
void OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) override;
QAction* m_toggleGrid = {};
QAction* m_toggleShadowCatcher = {};
AZStd::unordered_map<AZ::Render::DisplayMapperOperationType, QString> m_operationNames;
AZStd::unordered_map<AZ::Render::DisplayMapperOperationType, QAction*> m_operationActions;
};
} // namespace MaterialEditor
@@ -1,78 +1,40 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Window/ViewportSettingsInspector/ViewportSettingsInspector.h>
#include <Atom/Viewport/MaterialViewportRequestBus.h>
#include <AtomToolsFramework/Inspector/InspectorPropertyGroupWidget.h>
#include <AtomToolsFramework/Util/Util.h>
#include <Window/PresetBrowserDialogs/LightingPresetBrowserDialog.h>
#include <Window/PresetBrowserDialogs/ModelPresetBrowserDialog.h>
#include <Window/ViewportSettingsInspector/ViewportSettingsInspector.h>
#include <QAction>
#include <QApplication>
#include <QHBoxLayout>
#include <QPushButton>
#include <QToolButton>
#include <QAction>
#include <QHBoxLayout>
#include <QVBoxLayout>
namespace MaterialEditor
{
void GeneralViewportSettings::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<GeneralViewportSettings>()
->Version(1)
->Field("enableGrid", &GeneralViewportSettings::m_enableGrid)
->Field("enableShadowCatcher", &GeneralViewportSettings::m_enableShadowCatcher)
->Field("enableAlternateSkybox", &GeneralViewportSettings::m_enableAlternateSkybox)
->Field("fieldOfView", &GeneralViewportSettings::m_fieldOfView)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<GeneralViewportSettings>(
"GeneralViewportSettings", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &GeneralViewportSettings::m_enableGrid, "Enable Grid", "")
->DataElement(AZ::Edit::UIHandlers::Default, &GeneralViewportSettings::m_enableShadowCatcher, "Enable Shadow Catcher", "")
->DataElement(AZ::Edit::UIHandlers::Default, &GeneralViewportSettings::m_enableAlternateSkybox, "Enable Alternate Skybox", "")
->DataElement(AZ::Edit::UIHandlers::Slider, &GeneralViewportSettings::m_fieldOfView, "Field Of View", "")
->Attribute(AZ::Edit::Attributes::Min, 60.0f)
->Attribute(AZ::Edit::Attributes::Max, 120.0f)
;
}
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<GeneralViewportSettings>("GeneralViewportSettings")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "render")
->Constructor()
->Constructor<const GeneralViewportSettings&>()
->Property("enableGrid", BehaviorValueProperty(&GeneralViewportSettings::m_enableGrid))
->Property("enableShadowCatcher", BehaviorValueProperty(&GeneralViewportSettings::m_enableShadowCatcher))
->Property("enableAlternateSkybox", BehaviorValueProperty(&GeneralViewportSettings::m_enableAlternateSkybox))
->Property("fieldOfView", BehaviorValueProperty(&GeneralViewportSettings::m_fieldOfView))
;
}
}
ViewportSettingsInspector::ViewportSettingsInspector(QWidget* parent)
: AtomToolsFramework::InspectorWidget(parent)
{
m_viewportSettings =
AZ::UserSettings::CreateFind<MaterialViewportSettings>(AZ::Crc32("MaterialViewportSettings"), AZ::UserSettings::CT_GLOBAL);
m_windowSettings = AZ::UserSettings::CreateFind<MaterialEditorWindowSettings>(
AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL);
MaterialViewportNotificationBus::Handler::BusConnect();
}
@@ -84,7 +46,7 @@ namespace MaterialEditor
AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect();
}
void ViewportSettingsInspector::Popuate()
void ViewportSettingsInspector::Populate()
{
AddGroupsBegin();
AddGeneralGroup();
@@ -95,20 +57,21 @@ namespace MaterialEditor
void ViewportSettingsInspector::AddGeneralGroup()
{
const AZStd::string groupNameId = "general";
const AZStd::string groupDisplayName = "General";
const AZStd::string groupDescription = "General";
const AZStd::string groupNameId = "generalSettings";
const AZStd::string groupDisplayName = "General Settings";
const AZStd::string groupDescription = "General Settings";
AddGroup(
groupNameId, groupDisplayName, groupDescription,
new AtomToolsFramework::InspectorPropertyGroupWidget(&m_generalSettings, nullptr, m_generalSettings.TYPEINFO_Uuid(), this));
new AtomToolsFramework::InspectorPropertyGroupWidget(
m_viewportSettings.get(), nullptr, m_viewportSettings->TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupNameId)));
}
void ViewportSettingsInspector::AddModelGroup()
{
const AZStd::string groupNameId = "model";
const AZStd::string groupDisplayName = "Model";
const AZStd::string groupDescription = "Model";
const AZStd::string groupNameId = "modelSettings";
const AZStd::string groupDisplayName = "Model Settings";
const AZStd::string groupDescription = "Model Settings";
auto groupWidget = new QWidget(this);
auto buttonGroupWidget = new QWidget(groupWidget);
@@ -134,7 +97,7 @@ namespace MaterialEditor
if (m_modelPreset)
{
auto inspectorWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
m_modelPreset.get(), nullptr, m_modelPreset.get()->TYPEINFO_Uuid(), this, groupWidget);
m_modelPreset.get(), nullptr, m_modelPreset.get()->TYPEINFO_Uuid(), this, groupWidget, GetGroupSaveStateKey(groupNameId));
groupWidget->layout()->addWidget(inspectorWidget);
}
@@ -193,9 +156,9 @@ namespace MaterialEditor
void ViewportSettingsInspector::AddLightingGroup()
{
const AZStd::string groupNameId = "lighting";
const AZStd::string groupDisplayName = "Lighting";
const AZStd::string groupDescription = "Lighting";
const AZStd::string groupNameId = "lightingSettings";
const AZStd::string groupDisplayName = "Lighting Settings";
const AZStd::string groupDescription = "Lighting Settings";
auto groupWidget = new QWidget(this);
auto buttonGroupWidget = new QWidget(groupWidget);
@@ -221,7 +184,8 @@ namespace MaterialEditor
if (m_lightingPreset)
{
auto inspectorWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
m_lightingPreset.get(), nullptr, m_lightingPreset.get()->TYPEINFO_Uuid(), this, groupWidget);
m_lightingPreset.get(), nullptr, m_lightingPreset.get()->TYPEINFO_Uuid(), this, groupWidget,
GetGroupSaveStateKey(groupNameId));
groupWidget->layout()->addWidget(inspectorWidget);
}
@@ -239,8 +203,7 @@ namespace MaterialEditor
AZ::Render::LightingPresetPtr preset;
MaterialViewportRequestBus::BroadcastResult(
preset, &MaterialViewportRequestBus::Events::AddLightingPreset, AZ::Render::LightingPreset());
MaterialViewportRequestBus::Broadcast(
&MaterialViewportRequestBus::Events::SaveLightingPreset, preset, savePath);
MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Events::SaveLightingPreset, preset, savePath);
MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Events::SelectLightingPreset, preset);
}
}
@@ -264,7 +227,8 @@ namespace MaterialEditor
MaterialViewportRequestBus::BroadcastResult(preset, &MaterialViewportRequestBus::Events::GetLightingPresetSelection);
AZStd::string defaultPath;
MaterialViewportRequestBus::BroadcastResult(defaultPath, &MaterialViewportRequestBus::Events::GetLightingPresetLastSavePath, preset);
MaterialViewportRequestBus::BroadcastResult(
defaultPath, &MaterialViewportRequestBus::Events::GetLightingPresetLastSavePath, preset);
if (defaultPath.empty())
{
@@ -292,12 +256,15 @@ namespace MaterialEditor
m_lightingPreset.reset();
MaterialViewportRequestBus::BroadcastResult(m_lightingPreset, &MaterialViewportRequestBus::Events::GetLightingPresetSelection);
MaterialViewportRequestBus::BroadcastResult(m_generalSettings.m_enableGrid, &MaterialViewportRequestBus::Events::GetGridEnabled);
MaterialViewportRequestBus::BroadcastResult(m_viewportSettings->m_enableGrid, &MaterialViewportRequestBus::Events::GetGridEnabled);
MaterialViewportRequestBus::BroadcastResult(
m_generalSettings.m_enableShadowCatcher, &MaterialViewportRequestBus::Events::GetShadowCatcherEnabled);
m_viewportSettings->m_enableShadowCatcher, &MaterialViewportRequestBus::Events::GetShadowCatcherEnabled);
MaterialViewportRequestBus::BroadcastResult(
m_generalSettings.m_enableAlternateSkybox, &MaterialViewportRequestBus::Events::GetAlternateSkyboxEnabled);
MaterialViewportRequestBus::BroadcastResult(m_generalSettings.m_fieldOfView, &MaterialViewportRequestBus::Handler::GetFieldOfView);
m_viewportSettings->m_enableAlternateSkybox, &MaterialViewportRequestBus::Events::GetAlternateSkyboxEnabled);
MaterialViewportRequestBus::BroadcastResult(
m_viewportSettings->m_fieldOfView, &MaterialViewportRequestBus::Handler::GetFieldOfView);
MaterialViewportRequestBus::BroadcastResult(
m_viewportSettings->m_displayMapperOperationType, &MaterialViewportRequestBus::Handler::GetDisplayMapperOperationType);
AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect();
AtomToolsFramework::InspectorWidget::Reset();
@@ -307,7 +274,7 @@ namespace MaterialEditor
{
if (m_lightingPreset != preset)
{
Popuate();
Populate();
}
}
@@ -315,31 +282,37 @@ namespace MaterialEditor
{
if (m_modelPreset != preset)
{
Popuate();
Populate();
}
}
void ViewportSettingsInspector::OnShadowCatcherEnabledChanged(bool enable)
{
m_generalSettings.m_enableShadowCatcher = enable;
m_viewportSettings->m_enableShadowCatcher = enable;
RefreshGroup("general");
}
void ViewportSettingsInspector::OnGridEnabledChanged(bool enable)
{
m_generalSettings.m_enableGrid = enable;
m_viewportSettings->m_enableGrid = enable;
RefreshGroup("general");
}
void ViewportSettingsInspector::OnAlternateSkyboxEnabledChanged(bool enable)
{
m_generalSettings.m_enableAlternateSkybox = enable;
m_viewportSettings->m_enableAlternateSkybox = enable;
RefreshGroup("general");
}
void ViewportSettingsInspector::OnFieldOfViewChanged(float fieldOfView)
{
m_generalSettings.m_fieldOfView = fieldOfView;
m_viewportSettings->m_fieldOfView = fieldOfView;
RefreshGroup("general");
}
void ViewportSettingsInspector::OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType)
{
m_viewportSettings->m_displayMapperOperationType = operationType;
RefreshGroup("general");
}
@@ -364,12 +337,14 @@ namespace MaterialEditor
{
MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnLightingPresetChanged, m_lightingPreset);
MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnModelPresetChanged, m_modelPreset);
MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Events::SetGridEnabled, m_generalSettings.m_enableGrid);
MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Events::SetGridEnabled, m_viewportSettings->m_enableGrid);
MaterialViewportRequestBus::Broadcast(
&MaterialViewportRequestBus::Events::SetShadowCatcherEnabled, m_generalSettings.m_enableShadowCatcher);
&MaterialViewportRequestBus::Events::SetShadowCatcherEnabled, m_viewportSettings->m_enableShadowCatcher);
MaterialViewportRequestBus::Broadcast(
&MaterialViewportRequestBus::Events::SetAlternateSkyboxEnabled, m_generalSettings.m_enableAlternateSkybox);
MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Handler::SetFieldOfView, m_generalSettings.m_fieldOfView);
&MaterialViewportRequestBus::Events::SetAlternateSkyboxEnabled, m_viewportSettings->m_enableAlternateSkybox);
MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Handler::SetFieldOfView, m_viewportSettings->m_fieldOfView);
MaterialViewportRequestBus::Broadcast(
&MaterialViewportRequestBus::Handler::SetDisplayMapperOperationType, m_viewportSettings->m_displayMapperOperationType);
}
AZStd::string ViewportSettingsInspector::GetDefaultUniqueSaveFilePath(const AZStd::string& baseName) const
@@ -382,6 +357,28 @@ namespace MaterialEditor
savePath = AtomToolsFramework::GetUniqueFileInfo(savePath.c_str()).absoluteFilePath().toUtf8().constData();
return savePath;
}
AZ::Crc32 ViewportSettingsInspector::GetGroupSaveStateKey(const AZStd::string& groupNameId) const
{
return AZ::Crc32(AZStd::string::format("ViewportSettingsInspector::PropertyGroup::%s", groupNameId.c_str()));
}
bool ViewportSettingsInspector::ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const
{
auto stateItr = m_windowSettings->m_inspectorCollapsedGroups.find(GetGroupSaveStateKey(groupNameId));
return stateItr == m_windowSettings->m_inspectorCollapsedGroups.end();
}
void ViewportSettingsInspector::OnGroupExpanded(const AZStd::string& groupNameId)
{
m_windowSettings->m_inspectorCollapsedGroups.erase(GetGroupSaveStateKey(groupNameId));
}
void ViewportSettingsInspector::OnGroupCollapsed(const AZStd::string& groupNameId)
{
m_windowSettings->m_inspectorCollapsedGroups.insert(GetGroupSaveStateKey(groupNameId));
}
} // namespace MaterialEditor
#include <Source/Window/ViewportSettingsInspector/moc_ViewportSettingsInspector.cpp>
@@ -13,27 +13,18 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <Atom/Viewport/MaterialViewportNotificationBus.h>
#include <ACES/Aces.h>
#include <Atom/Feature/Utils/LightingPreset.h>
#include <Atom/Feature/Utils/ModelPreset.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h>
#include <Atom/Viewport/MaterialViewportNotificationBus.h>
#include <Atom/Viewport/MaterialViewportSettings.h>
#include <Atom/Window/MaterialEditorWindowSettings.h>
#include <AtomToolsFramework/Inspector/InspectorWidget.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h>
#endif
namespace MaterialEditor
{
struct GeneralViewportSettings
{
AZ_TYPE_INFO(GeneralViewportSettings, "{16150503-A314-4765-82A3-172670C9EA90}");
AZ_CLASS_ALLOCATOR(GeneralViewportSettings, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* context);
bool m_enableGrid = true;
bool m_enableShadowCatcher = true;
bool m_enableAlternateSkybox = false;
float m_fieldOfView = 90.0f;
};
//! Provides controls for viewing and editing a material document settings.
//! The settings can be divided into cards, with each one showing a subset of properties.
class ViewportSettingsInspector
@@ -49,7 +40,7 @@ namespace MaterialEditor
~ViewportSettingsInspector() override;
private:
void Popuate();
void Populate();
void AddGeneralGroup();
void AddModelGroup();
@@ -74,6 +65,7 @@ namespace MaterialEditor
void OnGridEnabledChanged(bool enable) override;
void OnAlternateSkyboxEnabledChanged(bool enable) override;
void OnFieldOfViewChanged(float fieldOfView) override;
void OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) override;
// AzToolsFramework::IPropertyEditorNotify overrides...
void BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode) override;
@@ -87,8 +79,14 @@ namespace MaterialEditor
AZStd::string GetDefaultUniqueSaveFilePath(const AZStd::string& baseName) const;
GeneralViewportSettings m_generalSettings;
AZ::Crc32 GetGroupSaveStateKey(const AZStd::string& groupNameId) const;
bool ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const override;
void OnGroupExpanded(const AZStd::string& groupNameId) override;
void OnGroupCollapsed(const AZStd::string& groupNameId) override;
AZ::Render::ModelPresetPtr m_modelPreset;
AZ::Render::LightingPresetPtr m_lightingPreset;
AZStd::intrusive_ptr<MaterialViewportSettings> m_viewportSettings;
AZStd::intrusive_ptr<MaterialEditorWindowSettings> m_windowSettings;
};
} // namespace MaterialEditor
@@ -1,30 +1,31 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#if !defined(Q_MOC_RUN)
#include <MaterialEditorApplication.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzQtComponents/Components/StyleManager.h>
#include <AzQtComponents/Utilities/QtPluginPaths.h>
#include <AzQtComponents/Components/GlobalEventFilter.h>
#include <AzQtComponents/Components/StyledDockWidget.h>
#include <AzQtComponents/Components/O3DEStylesheet.h>
#include <AzQtComponents/Utilities/QtPluginPaths.h>
#include <AzQtComponents/Utilities/HandleDpiAwareness.h>
#include <AzQtComponents/Components/StyleManager.h>
#include <AzQtComponents/Components/StyledDockWidget.h>
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
#include <AzQtComponents/Utilities/HandleDpiAwareness.h>
#include <AzQtComponents/Utilities/QtPluginPaths.h>
#include <QtWidgets/QApplication>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <Source/MaterialEditorApplication.h>
#include <QtWidgets/QApplication>
#endif
int main(int argc, char** argv)
{
@@ -45,15 +46,16 @@ int main(int argc, char** argv)
AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware);
MaterialEditor::MaterialEditorApplication app(&argc, &argv);
auto globalEventFilter = new AzQtComponents::GlobalEventFilter(&app);
app.installEventFilter(globalEventFilter);
AZ::IO::FixedMaxPath engineRootPath;
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
}
auto globalEventFilter = new AzQtComponents::GlobalEventFilter(&app);
app.installEventFilter(globalEventFilter);
AzQtComponents::StyleManager styleManager(&app);
styleManager.initialize(&app, engineRootPath);
@@ -13,7 +13,5 @@ set(FILES
Source/main.cpp
Source/MaterialEditorApplication.cpp
Source/MaterialEditorApplication.h
Include/Atom/Document/MaterialDocumentModule.h
Source/Document/MaterialDocumentModule.cpp
tool_dependencies.cmake
)
@@ -14,11 +14,11 @@ set(FILES
Include/Atom/Document/MaterialDocumentSystemRequestBus.h
Include/Atom/Document/MaterialDocumentNotificationBus.h
Include/Atom/Document/MaterialDocumentRequestBus.h
Include/Atom/Document/MaterialEditorSettingsBus.h
Include/Atom/Document/MaterialDocumentSettings.h
Source/Document/MaterialDocumentModule.cpp
Source/Document/MaterialDocumentSystemComponent.cpp
Source/Document/MaterialDocumentSystemComponent.h
Source/Document/MaterialDocument.cpp
Source/Document/MaterialDocument.h
Source/Document/MaterialEditorSettings.cpp
Source/Document/MaterialEditorSettings.h
Source/Document/MaterialDocumentSettings.cpp
)
@@ -12,6 +12,7 @@
set(FILES
Include/Atom/Viewport/InputController/MaterialEditorViewportInputControllerBus.h
Include/Atom/Viewport/MaterialViewportModule.h
Include/Atom/Viewport/MaterialViewportSettings.h
Include/Atom/Viewport/MaterialViewportRequestBus.h
Include/Atom/Viewport/MaterialViewportNotificationBus.h
Include/Atom/Viewport/PerformanceMetrics.h
@@ -35,6 +36,7 @@ set(FILES
Source/Viewport/InputController/RotateModelBehavior.cpp
Source/Viewport/InputController/RotateModelBehavior.h
Source/Viewport/MaterialViewportModule.cpp
Source/Viewport/MaterialViewportSettings.cpp
Source/Viewport/MaterialViewportComponent.cpp
Source/Viewport/MaterialViewportComponent.h
Source/Viewport/MaterialViewportWidget.cpp
@@ -11,6 +11,7 @@
set(FILES
Include/Atom/Window/MaterialEditorWindowModule.h
Include/Atom/Window/MaterialEditorWindowSettings.h
Include/Atom/Window/MaterialEditorWindowNotificationBus.h
Include/Atom/Window/MaterialEditorWindowRequestBus.h
Include/Atom/Window/MaterialEditorWindowFactoryRequestBus.h
@@ -19,6 +20,7 @@ set(FILES
Source/Window/MaterialEditorWindow.h
Source/Window/MaterialEditorWindow.cpp
Source/Window/MaterialEditorWindowModule.cpp
Source/Window/MaterialEditorWindowSettings.cpp
Source/Window/MaterialBrowserWidget.h
Source/Window/MaterialBrowserWidget.cpp
Source/Window/MaterialBrowserWidget.ui
@@ -26,6 +28,10 @@ set(FILES
Source/Window/MaterialEditor.qss
Source/Window/MaterialEditorWindowComponent.h
Source/Window/MaterialEditorWindowComponent.cpp
Source/Window/SettingsDialog/SettingsDialog.cpp
Source/Window/SettingsDialog/SettingsDialog.h
Source/Window/SettingsDialog/SettingsWidget.cpp
Source/Window/SettingsDialog/SettingsWidget.h
Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp
Source/Window/CreateMaterialDialog/CreateMaterialDialog.h
Source/Window/CreateMaterialDialog/CreateMaterialDialog.ui
@@ -10,6 +10,7 @@
#
set(GEM_DEPENDENCIES
Gem::Atom_RHI_Null.Private
Gem::Atom_RHI_DX12.Private
Gem::Atom_RHI_Vulkan.Private
Gem::Atom_RHI.Private
-58
View File
@@ -1,58 +0,0 @@
{
"gem_name": "MaterialEditor",
"Dependencies": [
{
"Uuid": "a218db9eb2114477b46600fea4441a6c",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RPI"
},
{
"Uuid": "b58e5eed0901428ca78544b04dbd61bd",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom Feature Common"
},
{
"Uuid": "b658359393884c4381c2fe2952b1472a",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "EditorPythonBindings"
},
{
"Uuid": "3e0ee0c27f204f5188146baac822d020",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "AtomToolsFramework"
},
{
"Uuid": "9d10b00be96045caa64c705e5772cb64",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "ImageProcessingAtom"
},
{
"Uuid": "4e981f3b17394f5d84d674fff0f54f4f",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "AtomLyIntegration.CommonFeatures"
}
],
"GemFormatVersion": 4,
"Uuid": "36f854c260b84d438dde4bc5789d8123",
"Name": "MaterialEditor",
"DisplayName": "Material Editor",
"Version": "0.1.0",
"LinkType": "Dynamic",
"Summary": "Tools for editing Atom materials",
"Tags": ["Untagged"],
"IconPath": "preview.svg",
"Modules": [
]
}
+17 -6
View File
@@ -1,9 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="140px" height="80px" viewBox="0 0 140 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background: #3D3D3D;">
<title>Icons / Project Configurator / Gems / Material Editor</title>
<g id="Icons-/-Project-Configurator-/-Gems-/-Material-Editor" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect fill="#3D3D3D" x="0" y="0" width="140" height="80"></rect>
<rect id="Rectangle" fill="#3D3D3D" x="0" y="0" width="140" height="80"></rect>
<path d="M73.2408742,13.1546686 L73.5657106,13.2306181 C85.906012,14.8406656 95.5585578,24.701494 96.85234,37.1420953 L96.9210589,37.9069399 C96.9730868,38.3746085 97,38.8420235 97,39.306992 L96.9962868,39.5446661 L97,40 L97,40 C97,54.9727273 84.9727273,67 70,67 C55.0272727,67 43,54.9727273 43,40 C43,25.0272727 55.0272727,13 70,13 C70.4866296,13 70.9701478,13.0127046 71.4502429,13.0378021 C71.8438705,12.9761732 72.3100032,12.9915388 72.835667,13.0772753 L73.2408742,13.1546686 Z M70.4576271,50.5254237 L63.1355932,50.5263757 L63.30962,51.2793289 C64.9262977,57.9629917 67.8804497,62.1213112 70.2023411,62.4098089 L70.4576271,62.4237288 L70.4576271,50.5254237 Z M58.9293184,49.6101695 L50.3220339,49.6101695 L50.7601942,50.4306198 C53.3341147,55.0138675 57.4385142,58.4714946 62.220339,60.5932203 C61.0051929,58.1969183 60.1140858,55.1616025 59.4174021,51.9984838 L59.1650061,50.807322 L58.9293184,49.6101695 Z M70.4576271,34.9661017 L63.3777731,34.9681606 L63.2783387,35.6436273 C63.1956538,36.3347889 63.1602174,37.0702243 63.1450304,37.8246341 L63.1355932,38.5844316 L63.1355932,40.502373 C63.1394993,41.1392466 63.1512177,41.7687999 63.1863729,42.376392 L63.2586362,43.2694792 L63.3777731,44.1186441 L70.4576271,44.1181865 L70.4576271,34.9661017 Z M58.2914427,34.9661017 L48.1120298,34.9661017 L47.9534452,35.8154576 C47.7477139,36.979661 47.5762712,38.2610169 47.5762712,39.5423729 C47.5762712,40.5033898 47.6727077,41.4644068 47.8077189,42.376 L47.9534452,43.2692881 L48.1120298,44.1186441 L58.559322,44.1186441 L58.4285969,43.1814237 C58.3600198,42.5700339 58.3257313,41.9806102 58.308587,41.3838644 L58.2935858,40.4795932 L58.2914427,34.9661017 Z M70.4576271,17.5762712 C68.1852718,17.5762712 65.2077027,21.4954965 63.4946548,27.989603 L63.30962,28.7216983 L63.1355932,29.4745763 L70.4576271,29.4729105 L70.4576271,17.5762712 L70.4576271,17.5762712 Z M62.220339,19.4067797 C57.5932203,21.403698 53.7495292,24.5839753 51.2115505,28.7722993 L50.7511084,29.5693802 L50.3220339,30.3898305 L58.75,30.3898305 L58.9877182,29.192678 C59.7440042,25.6072111 60.8817797,22.1026194 62.220339,19.4067797 Z" id="Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
<svg width="256px" height="256px" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icons / Application Icons / Material Editor</title>
<defs>
<polygon id="path-1" points="7.67007885e-15 0 256 0 256 256.000195 7.67007885e-15 256.000195"></polygon>
</defs>
<g id="Icons-/-Application-Icons-/-Material-Editor" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group" transform="translate(-0.000000, 0.000000)">
<g id="Fill-1-Clipped" transform="translate(-0.000000, 0.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="path-1"></g>
<path d="M184.641349,-0.000129743592 L71.3589754,-0.000129743592 C32.1115389,-0.000129743592 7.67007885e-15,32.1114092 7.67007885e-15,71.3588457 L7.67007885e-15,184.641219 C7.67007885e-15,223.888656 32.1115389,256.000195 71.3589754,256.000195 L184.641349,256.000195 C223.888785,256.000195 256.000324,223.888656 256.000324,184.641219 L256.000324,71.3588457 C256.000324,32.1114092 223.888785,-0.000129743592 184.641349,-0.000129743592" id="Fill-1" fill="#1E70EB" fill-rule="nonzero" mask="url(#mask-2)"></path>
</g>
<path d="M128.000162,32.2473156 C74.9006511,32.2473156 32.2467966,74.9005214 32.2467966,128.000681 C32.2467966,181.099543 74.9006511,223.752749 128.000162,223.752749 C181.099673,223.752749 223.752879,181.099543 223.752879,128.000681 C223.752879,74.9005214 181.099673,32.2473156 128.000162,32.2473156 L128.000162,32.2473156 Z M198.508668,93.1813935 L168.912209,93.1813935 C166.301119,79.2534189 162.81945,65.3254443 157.595973,54.8797877 C175.005617,62.7143545 189.804171,75.7717496 198.508668,93.1813935 L198.508668,93.1813935 Z M154.114304,128.000681 C154.114304,134.09344 154.114304,140.186848 153.243724,145.409676 L102.755952,145.409676 C101.885372,140.186848 101.885372,134.09344 101.885372,128.000681 C101.885372,121.906625 101.885372,115.813217 102.755952,110.590389 L153.243724,110.590389 C154.114304,115.813217 154.114304,121.906625 154.114304,128.000681 L154.114304,128.000681 Z M128.000162,206.343105 C120.165595,206.343105 109.719939,189.804041 104.497111,162.81932 L150.632634,162.81932 C146.280386,189.804041 135.83408,206.343105 128.000162,206.343105 L128.000162,206.343105 Z M104.497111,93.1813935 C109.719939,66.1960238 120.165595,49.6569595 128.000162,49.6569595 C135.83408,49.6569595 146.280386,66.1960238 151.502565,93.1813935 L104.497111,93.1813935 Z M99.2742823,54.8797877 C94.0508053,65.3254443 89.6985565,79.2534189 87.0874667,93.1813935 L57.4910073,93.1813935 C66.1961536,75.7717496 80.9940589,62.7143545 99.2742823,54.8797877 L99.2742823,54.8797877 Z M51.3975995,110.590389 L84.4757282,110.590389 L84.4757282,128.000681 C84.4757282,134.09344 84.4757282,139.316269 85.3463077,145.409676 L51.3975995,145.409676 C50.52702,140.186848 49.6564405,134.09344 49.6564405,128.000681 C49.6564405,121.906625 50.52702,115.813217 51.3975995,110.590389 L51.3975995,110.590389 Z M57.4910073,162.81932 L87.0874667,162.81932 C89.6985565,176.746646 93.1808745,190.674621 98.4037028,201.120277 C80.9940589,193.28571 66.1961536,180.228964 57.4910073,162.81932 L57.4910073,162.81932 Z M156.725393,201.120277 C161.948222,190.674621 166.301119,177.617874 168.042278,162.81932 L197.638089,162.81932 C189.804171,180.228964 175.005617,193.28571 156.725393,201.120277 L156.725393,201.120277 Z M204.602076,145.409676 L171.523947,145.409676 C172.394527,139.316269 172.394527,134.09344 172.394527,128.000681 C172.394527,121.906625 172.394527,116.683796 171.523947,110.590389 L204.602076,110.590389 C205.472656,115.813217 206.343235,121.906625 206.343235,128.000681 C206.343235,134.09344 205.472656,140.186848 204.602076,145.409676 L204.602076,145.409676 Z" id="Fill-4" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M128.000162,212.590259 L128.000162,125.542689 L128.000162,38.4944696 C128.000162,12.3803281 223.752879,73.3137573 223.752879,125.542689 C223.752879,177.770972 128.000162,238.705049 128.000162,212.590259" id="Fill-6" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB