Merge branch 'main' into ly-as-sdk/LYN-2948
This commit is contained in:
@@ -38,6 +38,13 @@
|
||||
"Gems/PrimitiveAssets"
|
||||
]
|
||||
},
|
||||
"MaterialEditor":
|
||||
{
|
||||
"SourcePaths":
|
||||
[
|
||||
"Gems/Atom/Tools/MaterialEditor"
|
||||
]
|
||||
},
|
||||
"UiBasics":
|
||||
{
|
||||
"SourcePaths":
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Scene::UnsetSubsystem(const T& system)
|
||||
bool Scene::UnsetSubsystem([[maybe_unused]] const T& system)
|
||||
{
|
||||
const AZ::TypeId& targetType = azrtti_typeid<T>();
|
||||
const size_t systemKeysCount = m_systemKeys.size();
|
||||
|
||||
@@ -770,8 +770,8 @@ namespace AzToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
Template& sourceTemplate = sourceTemplateReference->get();
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
Template& sourceTemplate = sourceTemplateReference->get();
|
||||
Template& targetTemplate = targetTemplateReference->get();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ set(FILES
|
||||
native/ui/GoToButton.h
|
||||
native/ui/GoToButton.cpp
|
||||
native/ui/GoToButton.ui
|
||||
native/ui/MainWindow.h
|
||||
native/ui/JobTreeViewItemDelegate.h
|
||||
native/ui/JobTreeViewItemDelegate.cpp
|
||||
native/ui/MainWindow.ui
|
||||
native/ui/MainWindow.cpp
|
||||
native/ui/MainWindow.ui
|
||||
native/ui/ProductAssetDetailsPanel.h
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 "JobTreeViewItemDelegate.h"
|
||||
|
||||
namespace AssetProcessor
|
||||
{
|
||||
void JobTreeViewItemDelegate::initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const
|
||||
{
|
||||
AzQtComponents::TableViewItemDelegate::initStyleOption(option, index);
|
||||
|
||||
option->features &= ~(QStyleOptionViewItem::WrapText);
|
||||
}
|
||||
}
|
||||
|
||||
#include <native/ui/moc_JobTreeViewItemDelegate.cpp>
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 <AzQtComponents/Components/Widgets/TableView.h>
|
||||
#endif
|
||||
|
||||
namespace AssetProcessor
|
||||
{
|
||||
class JobTreeViewItemDelegate
|
||||
: public AzQtComponents::TableViewItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using AzQtComponents::TableViewItemDelegate::TableViewItemDelegate;
|
||||
|
||||
protected:
|
||||
void initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const override;
|
||||
};
|
||||
} // namespace AssetProcessor
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <native/resourcecompiler/JobsModel.h>
|
||||
#include "native/ui/ui_MainWindow.h"
|
||||
#include "native/ui/JobTreeViewItemDelegate.h"
|
||||
|
||||
|
||||
#include "../utilities/GUIApplicationManager.h"
|
||||
@@ -221,6 +222,7 @@ void MainWindow::Activate()
|
||||
ui->jobTreeView->setModel(m_jobSortFilterProxy);
|
||||
ui->jobTreeView->setSortingEnabled(true);
|
||||
ui->jobTreeView->header()->setDefaultAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
|
||||
ui->jobTreeView->setItemDelegate(new AssetProcessor::JobTreeViewItemDelegate(ui->jobTreeView));
|
||||
|
||||
ui->jobTreeView->setToolTip(tr("Click to view Job Log"));
|
||||
|
||||
|
||||
@@ -25,9 +25,12 @@ namespace AZ
|
||||
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
|
||||
if (behaviorContext)
|
||||
{
|
||||
behaviorContext->Class<DataTypes::IGraphObject>();
|
||||
|
||||
behaviorContext->Class<GraphObjectProxy>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene.graph")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Method("CastWithTypeName", &GraphObjectProxy::CastWithTypeName)
|
||||
->Method("Invoke", &GraphObjectProxy::Invoke)
|
||||
;
|
||||
|
||||
@@ -33,6 +33,7 @@ ly_add_target(
|
||||
AZ::AzQtComponents
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Gui
|
||||
3rdParty::Qt::Network
|
||||
3rdParty::Qt::Widgets
|
||||
3rdParty::Python
|
||||
Gem::Atom_RPI.Edit
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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/std/functional.h>
|
||||
#include <QByteArray>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QString>
|
||||
#endif
|
||||
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
//! A named local server that will manage connections and forward recieved data
|
||||
class LocalServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LocalServer();
|
||||
~LocalServer();
|
||||
|
||||
//! Start a named local server
|
||||
bool Connect(const QString& serverName);
|
||||
|
||||
//! Stop the server
|
||||
void Disconnect();
|
||||
|
||||
//! Get server status
|
||||
bool IsConnected() const;
|
||||
|
||||
using ReadHandler = AZStd::function<void(const QByteArray&)>;
|
||||
|
||||
//! Set a handler that recieved data will be forwarded to
|
||||
void SetReadHandler(ReadHandler handler);
|
||||
|
||||
private:
|
||||
void AddConnection(QLocalSocket* connection);
|
||||
void ReadFromConnection(QLocalSocket* connection);
|
||||
void DeleteConnection(QLocalSocket* connection);
|
||||
|
||||
QString m_serverName;
|
||||
QLocalServer m_server;
|
||||
ReadHandler m_readHandler;
|
||||
};
|
||||
} // namespace AtomToolsFramework
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 <QLocalSocket>
|
||||
#endif
|
||||
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
//! LocalSocket enables interprocess communication by establ;ishing a connection and sending data to a LocalServer
|
||||
class LocalSocket : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LocalSocket();
|
||||
~LocalSocket();
|
||||
|
||||
//! Attempt to connect to a named local server
|
||||
bool Connect(const QString& serverName);
|
||||
|
||||
//! Sever connection from server
|
||||
void Disconnect();
|
||||
|
||||
//! Get the sockets connection status
|
||||
bool IsConnected() const;
|
||||
|
||||
//! Send a stream of data to the connected local server
|
||||
bool Send(const QByteArray& buffer);
|
||||
|
||||
private:
|
||||
QString m_serverName;
|
||||
QLocalSocket m_socket;
|
||||
};
|
||||
} // namespace AtomToolsFramework
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 <AtomToolsFramework/Communication/LocalServer.h>
|
||||
#include <AzCore/Debug/Trace.h>
|
||||
#include <QString>
|
||||
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
LocalServer::LocalServer()
|
||||
{
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Creating local server\n");
|
||||
m_server.setSocketOptions(QLocalServer::WorldAccessOption);
|
||||
|
||||
QObject::connect(&m_server, &QLocalServer::newConnection, this, [this]() { AddConnection(m_server.nextPendingConnection()); });
|
||||
}
|
||||
|
||||
LocalServer::~LocalServer()
|
||||
{
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
bool LocalServer::Connect(const QString& serverName)
|
||||
{
|
||||
Disconnect();
|
||||
|
||||
m_serverName = serverName;
|
||||
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Starting: %s\n", m_serverName.toUtf8().constData());
|
||||
if (m_server.listen(m_serverName))
|
||||
{
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Started: %s\n", m_serverName.toUtf8().constData());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_server.serverError() == QAbstractSocket::AddressInUseError)
|
||||
{
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Restarting: %s\n", m_serverName.toUtf8().constData());
|
||||
Disconnect();
|
||||
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Starting: %s\n", m_serverName.toUtf8().constData());
|
||||
if (m_server.listen(m_serverName))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Starting failed: %s\n", m_serverName.toUtf8().constData());
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
void LocalServer::Disconnect()
|
||||
{
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Disconnecting: %s\n", m_serverName.toUtf8().constData());
|
||||
QLocalServer::removeServer(m_serverName);
|
||||
}
|
||||
|
||||
bool LocalServer::IsConnected() const
|
||||
{
|
||||
return m_server.isListening();
|
||||
}
|
||||
|
||||
void LocalServer::SetReadHandler(LocalServer::ReadHandler handler)
|
||||
{
|
||||
m_readHandler = handler;
|
||||
}
|
||||
|
||||
void LocalServer::AddConnection(QLocalSocket* connection)
|
||||
{
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Connection added: %s\n", m_serverName.toUtf8().constData());
|
||||
QObject::connect(connection, &QLocalSocket::readyRead, this, [this, connection]() { ReadFromConnection(connection); });
|
||||
QObject::connect(connection, &QLocalSocket::disconnected, this, [this, connection]() { DeleteConnection(connection); });
|
||||
}
|
||||
|
||||
void LocalServer::ReadFromConnection(QLocalSocket* connection)
|
||||
{
|
||||
if (connection)
|
||||
{
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Data received: %s\n", m_serverName.toUtf8().constData());
|
||||
QByteArray buffer = connection->readAll();
|
||||
if (m_readHandler)
|
||||
{
|
||||
m_readHandler(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LocalServer::DeleteConnection(QLocalSocket* connection)
|
||||
{
|
||||
if (connection)
|
||||
{
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Deleting connection: %s\n", m_serverName.toUtf8().constData());
|
||||
connection->deleteLater();
|
||||
}
|
||||
}
|
||||
} // namespace AtomToolsFramework
|
||||
|
||||
#include <AtomToolsFramework/Communication/moc_LocalServer.cpp>
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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 <AtomToolsFramework/Communication/LocalSocket.h>
|
||||
#include <AzCore/Debug/Trace.h>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
LocalSocket::LocalSocket()
|
||||
{
|
||||
}
|
||||
|
||||
LocalSocket::~LocalSocket()
|
||||
{
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
bool LocalSocket::Connect(const QString& serverName)
|
||||
{
|
||||
Disconnect();
|
||||
|
||||
m_serverName = serverName;
|
||||
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Connecting to: %s\n", m_serverName.toUtf8().constData());
|
||||
m_socket.connectToServer(m_serverName);
|
||||
|
||||
if (IsConnected())
|
||||
{
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Waiting for connection to: %s\n", m_serverName.toUtf8().constData());
|
||||
if (m_socket.waitForConnected())
|
||||
{
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Connected to: %s\n", m_serverName.toUtf8().constData());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Connecting failed: %s\n", m_serverName.toUtf8().constData());
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
void LocalSocket::Disconnect()
|
||||
{
|
||||
if (IsConnected())
|
||||
{
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Disconnecting from: %s\n", m_serverName.toUtf8().constData());
|
||||
m_socket.disconnectFromServer();
|
||||
m_socket.waitForDisconnected();
|
||||
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Closing socket\n");
|
||||
m_socket.close();
|
||||
}
|
||||
}
|
||||
|
||||
bool LocalSocket::IsConnected() const
|
||||
{
|
||||
return m_socket.isOpen();
|
||||
}
|
||||
|
||||
bool LocalSocket::Send(const QByteArray& buffer)
|
||||
{
|
||||
if (IsConnected())
|
||||
{
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Sending data to: %s\n", m_serverName.toUtf8().constData());
|
||||
m_socket.write(buffer);
|
||||
|
||||
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Waiting for write to: %s\n", m_serverName.toUtf8().constData());
|
||||
m_socket.waitForBytesWritten();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace AtomToolsFramework
|
||||
|
||||
#include <AtomToolsFramework/Communication/moc_LocalSocket.cpp>
|
||||
@@ -211,10 +211,7 @@ namespace AtomToolsFramework
|
||||
|
||||
AZStd::string DynamicProperty::GetDescription() const
|
||||
{
|
||||
return AZStd::string::format("%s%s(Script Name = '%s')",
|
||||
m_config.m_description.c_str(),
|
||||
m_config.m_description.empty() ? "" : "\n",
|
||||
m_config.m_id.GetCStr());
|
||||
return m_config.m_description;
|
||||
}
|
||||
|
||||
AZ::Crc32 DynamicProperty::GetVisibility() const
|
||||
|
||||
@@ -91,6 +91,13 @@ namespace AtomToolsFramework
|
||||
propertyConfig.m_vectorLabels = propertyDefinition.m_vectorLabels;
|
||||
propertyConfig.m_visible = propertyDefinition.m_visibility != AZ::RPI::MaterialPropertyVisibility::Hidden;
|
||||
propertyConfig.m_readOnly = propertyDefinition.m_visibility == AZ::RPI::MaterialPropertyVisibility::Disabled;
|
||||
|
||||
// Update the description for material properties to include script name assuming id is set beforehand
|
||||
propertyConfig.m_description = AZStd::string::format(
|
||||
"%s%s(Script Name = '%s')",
|
||||
propertyConfig.m_description.c_str(),
|
||||
propertyConfig.m_description.empty() ? "" : "\n",
|
||||
propertyConfig.m_id.GetCStr());
|
||||
}
|
||||
|
||||
void ConvertToPropertyConfig(AtomToolsFramework::DynamicPropertyConfig& propertyConfig, const AZ::RPI::MaterialPropertyDynamicMetadata& propertyMetaData)
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Include/AtomToolsFramework/Communication/LocalServer.h
|
||||
Include/AtomToolsFramework/Communication/LocalSocket.h
|
||||
Include/AtomToolsFramework/Debug/TraceRecorder.h
|
||||
Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h
|
||||
Include/AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h
|
||||
@@ -22,6 +24,8 @@ set(FILES
|
||||
Include/AtomToolsFramework/Util/MaterialPropertyUtil.h
|
||||
Include/AtomToolsFramework/Util/Util.h
|
||||
Include/AtomToolsFramework/Viewport/RenderViewportWidget.h
|
||||
Source/Communication/LocalServer.cpp
|
||||
Source/Communication/LocalSocket.cpp
|
||||
Source/Debug/TraceRecorder.cpp
|
||||
Source/DynamicProperty/DynamicProperty.cpp
|
||||
Source/DynamicProperty/DynamicPropertyGroup.cpp
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
@@ -792,7 +794,8 @@ namespace MaterialEditor
|
||||
propertyConfig.m_nameId = "materialType";
|
||||
propertyConfig.m_displayName = "Material Type";
|
||||
propertyConfig.m_groupName = "Details";
|
||||
propertyConfig.m_description = propertyConfig.m_displayName;
|
||||
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;
|
||||
@@ -806,7 +809,8 @@ namespace MaterialEditor
|
||||
propertyConfig.m_nameId = "parentMaterial";
|
||||
propertyConfig.m_displayName = "Parent Material";
|
||||
propertyConfig.m_groupName = "Details";
|
||||
propertyConfig.m_description = propertyConfig.m_displayName;
|
||||
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;
|
||||
|
||||
@@ -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>(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
-16
@@ -109,7 +109,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));
|
||||
@@ -135,31 +134,16 @@ namespace MaterialEditor
|
||||
m_documentMap.clear();
|
||||
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>();
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#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/MaterialDocumentSystemRequestBus.h>
|
||||
@@ -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
|
||||
{
|
||||
@@ -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;
|
||||
|
||||
@@ -90,6 +90,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();
|
||||
@@ -299,12 +307,12 @@ namespace MaterialEditor
|
||||
return false;
|
||||
}
|
||||
|
||||
void MaterialEditorApplication::ProcessCommandLine()
|
||||
void MaterialEditorApplication::ProcessCommandLine(const AZ::CommandLine& commandLine)
|
||||
{
|
||||
const AZStd::string timeoputSwitchName = "timeout";
|
||||
if (m_commandLine.HasSwitch(timeoputSwitchName))
|
||||
if (commandLine.HasSwitch(timeoputSwitchName))
|
||||
{
|
||||
const AZStd::string& timeoutValue = m_commandLine.GetSwitchValue(timeoputSwitchName, 0);
|
||||
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 +323,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 +337,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 +417,50 @@ 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:");
|
||||
for (int argi = 1; argi < m_argC; ++argi)
|
||||
{
|
||||
buffer.append(QString(m_argV[argi]).append("\n").toUtf8());
|
||||
}
|
||||
m_socket.Send(buffer);
|
||||
m_socket.Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
return AtomToolsFramework::LaunchTool("GridHub", AZ_TRAIT_MATERIALEDITOR_EXT, arguments);
|
||||
// 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 +470,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 +487,6 @@ namespace MaterialEditor
|
||||
|
||||
LoadSettings();
|
||||
|
||||
LaunchDiscoveryService();
|
||||
|
||||
MaterialEditorWindowNotificationBus::Handler::BusConnect();
|
||||
|
||||
MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast(
|
||||
@@ -450,7 +501,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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
-2
@@ -13,7 +13,6 @@
|
||||
#include <Atom/Document/ShaderManagementConsoleDocumentModule.h>
|
||||
#include <Document/ShaderManagementConsoleDocumentSystemComponent.h>
|
||||
|
||||
#include <AzFramework/TargetManagement/TargetManagementComponent.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h>
|
||||
#include <AzToolsFramework/Asset/AssetSystemComponent.h>
|
||||
|
||||
@@ -32,7 +31,6 @@ namespace ShaderManagementConsole
|
||||
return AZ::ComponentTypeList{
|
||||
azrtti_typeid<AzToolsFramework::AssetSystem::AssetSystemComponent>(),
|
||||
azrtti_typeid<ShaderManagementConsoleDocumentSystemComponent>(),
|
||||
azrtti_typeid<AzFramework::TargetManagementComponent>(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
-16
@@ -105,7 +105,6 @@ namespace ShaderManagementConsole
|
||||
|
||||
void ShaderManagementConsoleDocumentSystemComponent::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));
|
||||
@@ -130,13 +129,11 @@ namespace ShaderManagementConsole
|
||||
{
|
||||
m_documentMap.clear();
|
||||
ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusConnect();
|
||||
AzFramework::TmMsgBus::Handler::BusConnect(AZ_CRC("OpenInShaderManagementConsole", 0x9f92aac8));
|
||||
}
|
||||
|
||||
void ShaderManagementConsoleDocumentSystemComponent::Deactivate()
|
||||
{
|
||||
ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusDisconnect();
|
||||
AzFramework::TmMsgBus::Handler::BusDisconnect();
|
||||
m_documentMap.clear();
|
||||
}
|
||||
|
||||
@@ -159,19 +156,6 @@ namespace ShaderManagementConsole
|
||||
return m_documentMap.erase(documentId) != 0;
|
||||
}
|
||||
|
||||
void ShaderManagementConsoleDocumentSystemComponent::OnReceivedMsg(AzFramework::TmMsgPtr msg)
|
||||
{
|
||||
if (msg->GetId() == AZ_CRC("OpenInShaderManagementConsole", 0x9f92aac8))
|
||||
{
|
||||
const char* documentPath = reinterpret_cast<const char*>(msg->GetCustomBlob());
|
||||
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, documentPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "We received a message of an unrecognized class type!");
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocument(AZStd::string_view path)
|
||||
{
|
||||
return OpenDocumentImpl(path, true);
|
||||
|
||||
-7
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
#include <AzFramework/TargetManagement/TargetManagementAPI.h>
|
||||
|
||||
#include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
|
||||
#include <Atom/RPI.Public/WindowContext.h>
|
||||
@@ -30,7 +29,6 @@ namespace ShaderManagementConsole
|
||||
//! ShaderManagementConsoleDocumentSystemComponent is the central component of the Shader Management Console Core gem
|
||||
class ShaderManagementConsoleDocumentSystemComponent
|
||||
: public AZ::Component
|
||||
, private AzFramework::TmMsgBus::Handler
|
||||
, private ShaderManagementConsoleDocumentSystemRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
@@ -55,11 +53,6 @@ namespace ShaderManagementConsole
|
||||
void Deactivate() override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// TmMsgBus::Handler overrides...
|
||||
void OnReceivedMsg(AzFramework::TmMsgPtr msg) override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// ShaderManagementConsoleDocumentSystemRequestBus::Handler overrides...
|
||||
AZ::Uuid CreateDocument() override;
|
||||
|
||||
+4
-1
@@ -245,9 +245,12 @@ namespace AZ
|
||||
for (const auto& propertyDefinition : propertyListItr->second)
|
||||
{
|
||||
AtomToolsFramework::DynamicPropertyConfig propertyConfig;
|
||||
|
||||
// Assign id before conversion so it can be used in dynamic description
|
||||
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName();
|
||||
|
||||
AtomToolsFramework::ConvertToPropertyConfig(propertyConfig, propertyDefinition);
|
||||
|
||||
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName();
|
||||
propertyConfig.m_groupName = groupDisplayName;
|
||||
const auto& propertyIndex = m_editData.m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyConfig.m_id);
|
||||
propertyConfig.m_showThumbnail = true;
|
||||
|
||||
+4
-31
@@ -93,7 +93,6 @@ namespace AZ
|
||||
|
||||
void EditorMaterialSystemComponent::Activate()
|
||||
{
|
||||
AzFramework::TargetManagerClient::Bus::Handler::BusConnect();
|
||||
EditorMaterialSystemComponentRequestBus::Handler::BusConnect();
|
||||
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect();
|
||||
@@ -105,7 +104,6 @@ namespace AZ
|
||||
|
||||
void EditorMaterialSystemComponent::Deactivate()
|
||||
{
|
||||
AzFramework::TargetManagerClient::Bus::Handler::BusDisconnect();
|
||||
EditorMaterialSystemComponentRequestBus::Handler::BusDisconnect();
|
||||
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect();
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect();
|
||||
@@ -123,36 +121,11 @@ namespace AZ
|
||||
|
||||
void EditorMaterialSystemComponent::OpenInMaterialEditor(const AZStd::string& sourcePath)
|
||||
{
|
||||
if (m_materialEditorTarget.IsValid())
|
||||
{
|
||||
AzFramework::TmMsg openDocumentMsg(AZ_CRC("OpenInMaterialEditor", 0x9f92aac8));
|
||||
openDocumentMsg.AddCustomBlob(sourcePath.c_str(), sourcePath.size() + 1);
|
||||
AzFramework::TargetManager::Bus::Broadcast(&AzFramework::TargetManager::SendTmMessage, m_materialEditorTarget, openDocumentMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_TracePrintf("MaterialComponent", "Launching Material Editor");
|
||||
AZ_TracePrintf("MaterialComponent", "Launching Material Editor");
|
||||
|
||||
QStringList arguments;
|
||||
arguments.append(sourcePath.c_str());
|
||||
AtomToolsFramework::LaunchTool("MaterialEditor", ".exe", arguments);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorMaterialSystemComponent::TargetJoinedNetwork(AzFramework::TargetInfo info)
|
||||
{
|
||||
if (AZ::StringFunc::Equal(info.GetDisplayName(), "MaterialEditor"))
|
||||
{
|
||||
m_materialEditorTarget = info;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorMaterialSystemComponent::TargetLeftNetwork(AzFramework::TargetInfo info)
|
||||
{
|
||||
if (AZ::StringFunc::Equal(info.GetDisplayName(), "MaterialEditor"))
|
||||
{
|
||||
m_materialEditorTarget = {};
|
||||
}
|
||||
QStringList arguments;
|
||||
arguments.append(sourcePath.c_str());
|
||||
AtomToolsFramework::LaunchTool("MaterialEditor", ".exe", arguments);
|
||||
}
|
||||
|
||||
void EditorMaterialSystemComponent::OnApplicationAboutToStop()
|
||||
|
||||
-9
@@ -14,7 +14,6 @@
|
||||
#include <AzCore/Component/Component.h>
|
||||
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <AzFramework/TargetManagement/TargetManagementAPI.h>
|
||||
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
@@ -32,7 +31,6 @@ namespace AZ
|
||||
class EditorMaterialSystemComponent
|
||||
: public AZ::Component
|
||||
, private EditorMaterialSystemComponentRequestBus::Handler
|
||||
, private AzFramework::TargetManagerClient::Bus::Handler
|
||||
, private AzFramework::ApplicationLifecycleEvents::Bus::Handler
|
||||
, public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler
|
||||
, public AzToolsFramework::EditorMenuNotificationBus::Handler
|
||||
@@ -57,10 +55,6 @@ namespace AZ
|
||||
//! EditorMaterialSystemComponentRequestBus::Handler overrides...
|
||||
void OpenInMaterialEditor(const AZStd::string& sourcePath) override;
|
||||
|
||||
//! AzFramework::TargetManagerClient::Bus::Handler overrides...
|
||||
void TargetJoinedNetwork(AzFramework::TargetInfo info) override;
|
||||
void TargetLeftNetwork(AzFramework::TargetInfo info) override;
|
||||
|
||||
// AzFramework::ApplicationLifecycleEvents overrides...
|
||||
void OnApplicationAboutToStop() override;
|
||||
|
||||
@@ -74,9 +68,6 @@ namespace AZ
|
||||
void SetupThumbnails();
|
||||
void TeardownThumbnails();
|
||||
|
||||
// Material Editor target for interprocess communication with MaterialEditor
|
||||
AzFramework::TargetInfo m_materialEditorTarget;
|
||||
|
||||
QAction* m_openMaterialEditorAction = nullptr;
|
||||
|
||||
AZStd::unique_ptr<MaterialBrowserInteractions> m_materialBrowserInteractions;
|
||||
|
||||
@@ -126,7 +126,12 @@ namespace AZ
|
||||
SetFilter(inputFilter);
|
||||
|
||||
// Bind our custom log handler.
|
||||
AZ::Interface<AZ::ILogger>::Get()->BindLogHandler(m_logHandler);
|
||||
AZ::ILogger* loggerInstance = AZ::Interface<AZ::ILogger>::Get();
|
||||
AZ_Assert(loggerInstance, "Failed to get ILogger instance. Log handler not bound.")
|
||||
if (loggerInstance)
|
||||
{
|
||||
loggerInstance->BindLogHandler(m_logHandler);
|
||||
}
|
||||
|
||||
// Connect to receive render tick events.
|
||||
auto atomViewportRequests = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace AZ
|
||||
#endif
|
||||
}
|
||||
|
||||
void ImguiAtomSystemComponent::OnViewportSizeChanged(AzFramework::WindowSize size)
|
||||
void ImguiAtomSystemComponent::OnViewportSizeChanged([[maybe_unused]] AzFramework::WindowSize size)
|
||||
{
|
||||
#if defined(IMGUI_ENABLED)
|
||||
ImGui::ImGuiManagerBus::Broadcast([this, size](ImGui::ImGuiManagerBus::Events* imgui)
|
||||
|
||||
@@ -360,7 +360,7 @@ namespace EMotionFX
|
||||
ApplyMorphSetup();
|
||||
UpdateSkinningMatrices();
|
||||
UpdateAttachments();
|
||||
}
|
||||
}
|
||||
|
||||
// update the bounds when needed
|
||||
if (GetBoundsUpdateEnabled() && mBoundsUpdateType != BOUNDS_MESH_BASED)
|
||||
@@ -418,7 +418,8 @@ namespace EMotionFX
|
||||
}
|
||||
|
||||
// Update the bounds when we are set to use mesh based bounds.
|
||||
if (GetBoundsUpdateEnabled() == BOUNDS_MESH_BASED)
|
||||
if (GetBoundsUpdateEnabled() &&
|
||||
GetBoundsUpdateType() == BOUNDS_MESH_BASED)
|
||||
{
|
||||
mBoundsUpdatePassedTime += timePassedInSeconds;
|
||||
if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency)
|
||||
@@ -449,7 +450,8 @@ namespace EMotionFX
|
||||
}
|
||||
|
||||
// Update the bounds when we are set to use mesh based bounds.
|
||||
if (GetBoundsUpdateEnabled() == BOUNDS_MESH_BASED)
|
||||
if (GetBoundsUpdateEnabled() &&
|
||||
GetBoundsUpdateType() == BOUNDS_MESH_BASED)
|
||||
{
|
||||
mBoundsUpdatePassedTime += timePassedInSeconds;
|
||||
if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency)
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// include the required headers
|
||||
#include <AzCore/Jobs/JobFunction.h>
|
||||
#include <AzCore/Jobs/JobCompletion.h>
|
||||
#include "EMotionFXConfig.h"
|
||||
#include "DualQuatSkinDeformer.h"
|
||||
#include "Mesh.h"
|
||||
@@ -23,138 +24,143 @@
|
||||
#include <EMotionFX/Source/Allocators.h>
|
||||
#include <MCore/Source/LogManager.h>
|
||||
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(DualQuatSkinDeformer, DeformerAllocator, 0)
|
||||
|
||||
// constructor
|
||||
DualQuatSkinDeformer::DualQuatSkinDeformer(Mesh* mesh)
|
||||
: MeshDeformer(mesh)
|
||||
{
|
||||
mBones.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_DEFORMERS);
|
||||
}
|
||||
|
||||
|
||||
// destructor
|
||||
DualQuatSkinDeformer::~DualQuatSkinDeformer()
|
||||
{
|
||||
mBones.Clear();
|
||||
}
|
||||
|
||||
AZ::Outcome<size_t> DualQuatSkinDeformer::FindLocalBoneIndex(uint32 nodeIndex) const
|
||||
{
|
||||
const size_t numBones = m_bones.size();
|
||||
for (size_t i = 0; i < numBones; ++i)
|
||||
{
|
||||
if (m_bones[i].mNodeNr == nodeIndex)
|
||||
{
|
||||
return AZ::Success(i);
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::Failure();
|
||||
}
|
||||
|
||||
// creation
|
||||
DualQuatSkinDeformer* DualQuatSkinDeformer::Create(Mesh* mesh)
|
||||
{
|
||||
return aznew DualQuatSkinDeformer(mesh);
|
||||
}
|
||||
|
||||
|
||||
// get the type id
|
||||
uint32 DualQuatSkinDeformer::GetType() const
|
||||
{
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
|
||||
// get the subtype id
|
||||
uint32 DualQuatSkinDeformer::GetSubType() const
|
||||
{
|
||||
return SUBTYPE_ID;
|
||||
}
|
||||
|
||||
|
||||
// clone this class
|
||||
MeshDeformer* DualQuatSkinDeformer::Clone(Mesh* mesh)
|
||||
{
|
||||
// create the new cloned deformer
|
||||
DualQuatSkinDeformer* result = aznew DualQuatSkinDeformer(mesh);
|
||||
|
||||
// copy the bone info (for precalc/optimization reasons)
|
||||
result->mBones = mBones;
|
||||
result->m_bones = m_bones;
|
||||
|
||||
// return the result
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// the main method where all calculations are done
|
||||
void DualQuatSkinDeformer::Update(ActorInstance* actorInstance, Node* node, float timeDelta)
|
||||
void DualQuatSkinDeformer::Update(ActorInstance* actorInstance, [[maybe_unused]] Node* node, [[maybe_unused]] float timeDelta)
|
||||
{
|
||||
AZ_UNUSED(node);
|
||||
MCORE_UNUSED(timeDelta);
|
||||
|
||||
const Actor* actor = actorInstance->GetActor();
|
||||
const Pose* pose = actorInstance->GetTransformData()->GetCurrentPose();
|
||||
const uint32 numVertices = mMesh->GetNumVertices();
|
||||
|
||||
AZ::Vector3 newPos, newNormal, newTangent, newBitangent;
|
||||
AZ::Vector3 vtxPos, normal, tangent, bitangent;
|
||||
AZ::Vector3* positions = static_cast<AZ::Vector3*>(mMesh->FindVertexData(Mesh::ATTRIB_POSITIONS));
|
||||
AZ::Vector3* normals = static_cast<AZ::Vector3*>(mMesh->FindVertexData(Mesh::ATTRIB_NORMALS));
|
||||
AZ::Vector4* tangents = static_cast<AZ::Vector4*>(mMesh->FindVertexData(Mesh::ATTRIB_TANGENTS));
|
||||
AZ::Vector3* bitangents = static_cast<AZ::Vector3*>(mMesh->FindVertexData(Mesh::ATTRIB_BITANGENTS));
|
||||
AZ::u32* orgVerts = static_cast<AZ::u32*>(mMesh->FindVertexData(Mesh::ATTRIB_ORGVTXNUMBERS));
|
||||
|
||||
// precalc the skinning matrices
|
||||
const uint32 numBones = mBones.GetLength();
|
||||
for (uint32 i = 0; i < numBones; i++)
|
||||
// pre-calculate the skinning matrices
|
||||
for (BoneInfo& boneInfo : m_bones)
|
||||
{
|
||||
const uint32 nodeIndex = mBones[i].mNodeNr;
|
||||
Transform skinTransform = actor->GetInverseBindPoseTransform(nodeIndex);
|
||||
skinTransform.Multiply(pose->GetModelSpaceTransform(nodeIndex));
|
||||
mBones[i].mDualQuat.FromRotationTranslation(skinTransform.mRotation, skinTransform.mPosition);
|
||||
const uint32 nodeIndex = boneInfo.mNodeNr;
|
||||
const Transform skinTransform = actor->GetInverseBindPoseTransform(nodeIndex) * pose->GetModelSpaceTransform(nodeIndex);
|
||||
boneInfo.mDualQuat.FromRotationTranslation(skinTransform.mRotation, skinTransform.mPosition);
|
||||
}
|
||||
|
||||
// find the skinning layer
|
||||
SkinningInfoVertexAttributeLayer* layer = (SkinningInfoVertexAttributeLayer*)mMesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID);
|
||||
MCORE_ASSERT(layer);
|
||||
AZ::JobCompletion jobCompletion;
|
||||
|
||||
// Split up the skinned vertices into batches.
|
||||
const AZ::u32 numBatches = aznumeric_caster(ceilf(aznumeric_cast<float>(numVertices) / aznumeric_cast<float>(s_numVerticesPerBatch)));
|
||||
for (AZ::u32 batchIndex = 0; batchIndex < numBatches; ++batchIndex)
|
||||
{
|
||||
const AZ::u32 startVertex = batchIndex * s_numVerticesPerBatch;
|
||||
const AZ::u32 endVertex = AZStd::min(startVertex + s_numVerticesPerBatch, numVertices);
|
||||
|
||||
// Create a job for every batch and skin them simultaneously.
|
||||
AZ::JobContext* jobContext = nullptr;
|
||||
AZ::Job* job = AZ::CreateJobFunction([this, startVertex, endVertex]()
|
||||
{
|
||||
SkinRange(mMesh, startVertex, endVertex, m_bones);
|
||||
}, /*isAutoDelete=*/true, jobContext);
|
||||
|
||||
job->SetDependent(&jobCompletion);
|
||||
job->Start();
|
||||
}
|
||||
|
||||
jobCompletion.StartAndWaitForCompletion();
|
||||
}
|
||||
|
||||
void DualQuatSkinDeformer::SkinRange(Mesh* mesh, AZ::u32 startVertex, AZ::u32 endVertex, const AZStd::vector<BoneInfo>& boneInfos)
|
||||
{
|
||||
SkinningInfoVertexAttributeLayer* layer = (SkinningInfoVertexAttributeLayer*)mesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID);
|
||||
AZ_Assert(layer, "Cannot find skinning layer.");
|
||||
|
||||
AZ::Vector3 newTangent;
|
||||
AZ::Vector3 vtxPos, normal, tangent, bitangent;
|
||||
AZ::u32 orgVertex;
|
||||
float weight;
|
||||
|
||||
AZ::Vector3* positions = static_cast<AZ::Vector3*>(mesh->FindVertexData(Mesh::ATTRIB_POSITIONS));
|
||||
AZ::Vector3* normals = static_cast<AZ::Vector3*>(mesh->FindVertexData(Mesh::ATTRIB_NORMALS));
|
||||
AZ::Vector4* tangents = static_cast<AZ::Vector4*>(mesh->FindVertexData(Mesh::ATTRIB_TANGENTS));
|
||||
AZ::Vector3* bitangents = static_cast<AZ::Vector3*>(mesh->FindVertexData(Mesh::ATTRIB_BITANGENTS));
|
||||
AZ::u32* orgVerts = static_cast<AZ::u32*>(mesh->FindVertexData(Mesh::ATTRIB_ORGVTXNUMBERS));
|
||||
|
||||
// if there are tangents and bitangents to skin
|
||||
if (tangents && bitangents)
|
||||
{
|
||||
const uint32 numVertices = mMesh->GetNumVertices();
|
||||
uint32 v = 0;
|
||||
uint32 orgVertex;
|
||||
|
||||
SkinInfluence* influence;
|
||||
BoneInfo* boneInfo;
|
||||
float weight;
|
||||
for (v = 0; v < numVertices; ++v)
|
||||
for (AZ::u32 v = startVertex; v < endVertex; ++v)
|
||||
{
|
||||
// get the original vertex number
|
||||
orgVertex = *(orgVerts++);
|
||||
|
||||
// reset the skinned position
|
||||
newPos = AZ::Vector3::CreateZero();
|
||||
newNormal = AZ::Vector3::CreateZero();
|
||||
newTangent = AZ::Vector3::CreateZero();
|
||||
newBitangent = AZ::Vector3::CreateZero();
|
||||
|
||||
const float tangentW = tangents->GetW();
|
||||
vtxPos.Set (positions->GetX(), positions->GetY(), positions->GetZ());
|
||||
normal.Set (normals->GetX(), normals->GetY(), normals->GetZ());
|
||||
tangent.Set (tangents->GetX(), tangents->GetY(), tangents->GetZ());
|
||||
bitangent.Set(bitangents->GetX(), bitangents->GetY(), bitangents->GetZ());
|
||||
orgVertex = orgVerts[v];
|
||||
vtxPos = positions[v];
|
||||
normal = normals[v];
|
||||
const float tangentW = tangents[v].GetW();
|
||||
tangent.Set(tangents[v].GetX(), tangents[v].GetY(), tangents[v].GetZ());
|
||||
bitangent = bitangents[v];
|
||||
|
||||
// process the skin influences for this vertex
|
||||
const size_t numInfluences = layer->GetNumInfluences(orgVertex);
|
||||
if (numInfluences > 0)
|
||||
{
|
||||
// get the pivot quat, used for the dot product check
|
||||
const MCore::DualQuaternion& pivotQuat = mBones[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat;
|
||||
const MCore::DualQuaternion& pivotQuat = boneInfos[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat;
|
||||
|
||||
// our skinning dual quaternion
|
||||
MCore::DualQuaternion skinQuat(AZ::Quaternion(0, 0, 0, 0), AZ::Quaternion(0, 0, 0, 0));
|
||||
|
||||
for (size_t i = 0; i < numInfluences; ++i)
|
||||
{
|
||||
// get the influence
|
||||
influence = layer->GetInfluence(orgVertex, i);
|
||||
boneInfo = &mBones[ influence->GetBoneNr() ];
|
||||
weight = influence->GetWeight();
|
||||
SkinInfluence* influence = layer->GetInfluence(orgVertex, i);
|
||||
weight = influence->GetWeight();
|
||||
|
||||
// check if we need to invert the dual quat
|
||||
MCore::DualQuaternion& influenceQuat = mBones[ influence->GetBoneNr() ].mDualQuat;
|
||||
MCore::DualQuaternion influenceQuat = boneInfos[ influence->GetBoneNr() ].mDualQuat;
|
||||
if (influenceQuat.mReal.Dot(pivotQuat.mReal) < 0.0f)
|
||||
{
|
||||
influenceQuat *= -1.0f;
|
||||
@@ -168,74 +174,50 @@ namespace EMotionFX
|
||||
skinQuat.Normalize();
|
||||
|
||||
// perform skinning
|
||||
newPos = skinQuat.TransformPoint(vtxPos);
|
||||
newNormal = skinQuat.TransformVector(normal);
|
||||
newTangent = skinQuat.TransformVector(tangent);
|
||||
newBitangent = skinQuat.TransformVector(bitangent);
|
||||
positions[v] = skinQuat.TransformPoint(vtxPos);
|
||||
normals[v] = skinQuat.TransformVector(normal);
|
||||
newTangent = skinQuat.TransformVector(tangent);
|
||||
tangents[v].Set(newTangent.GetX(), newTangent.GetY(), newTangent.GetZ(), tangentW);
|
||||
bitangents[v] = skinQuat.TransformVector(bitangent);
|
||||
}
|
||||
else
|
||||
{
|
||||
// perform the skinning
|
||||
newPos = vtxPos;
|
||||
newNormal = normal;
|
||||
newTangent = tangent;
|
||||
newBitangent = bitangent;
|
||||
// no skinning influences, just copy the values
|
||||
positions[v] = vtxPos;
|
||||
normals[v] = normal;
|
||||
newTangent = tangent;
|
||||
tangents[v].Set(newTangent.GetX(), newTangent.GetY(), newTangent.GetZ(), tangentW);
|
||||
bitangents[v] = bitangent;
|
||||
}
|
||||
|
||||
// output the skinned values
|
||||
positions->Set (newPos.GetX(), newPos.GetY(), newPos.GetZ());
|
||||
positions++;
|
||||
normals->Set (newNormal.GetX(), newNormal.GetY(), newNormal.GetZ());
|
||||
normals++;
|
||||
tangents->Set (newTangent.GetX(), newTangent.GetY(), newTangent.GetZ(), tangentW);
|
||||
tangents++;
|
||||
bitangents->Set (newBitangent.GetX(), newBitangent.GetY(), newBitangent.GetZ());
|
||||
bitangents++;
|
||||
}
|
||||
}
|
||||
else if (tangents && !bitangents) // tangents but no bitangents
|
||||
{
|
||||
const uint32 numVertices = mMesh->GetNumVertices();
|
||||
uint32 v = 0;
|
||||
uint32 orgVertex;
|
||||
|
||||
SkinInfluence* influence;
|
||||
BoneInfo* boneInfo;
|
||||
float weight;
|
||||
for (v = 0; v < numVertices; ++v)
|
||||
for (AZ::u32 v = startVertex; v < endVertex; ++v)
|
||||
{
|
||||
// get the original vertex number
|
||||
orgVertex = *(orgVerts++);
|
||||
|
||||
// reset the skinned position
|
||||
newPos = AZ::Vector3::CreateZero();
|
||||
newNormal = AZ::Vector3::CreateZero();
|
||||
newTangent = AZ::Vector3::CreateZero();
|
||||
|
||||
const float tangentW = tangents->GetW();
|
||||
vtxPos.Set (positions->GetX(), positions->GetY(), positions->GetZ());
|
||||
normal.Set (normals->GetX(), normals->GetY(), normals->GetZ());
|
||||
tangent.Set (tangents->GetX(), tangents->GetY(), tangents->GetZ());
|
||||
orgVertex = orgVerts[v];
|
||||
vtxPos = positions[v];
|
||||
normal = normals[v];
|
||||
const float tangentW = tangents[v].GetW();
|
||||
tangent.Set(tangents[v].GetX(), tangents[v].GetY(), tangents[v].GetZ());
|
||||
|
||||
// process the skin influences for this vertex
|
||||
const size_t numInfluences = layer->GetNumInfluences(orgVertex);
|
||||
if (numInfluences > 0)
|
||||
{
|
||||
// get the pivot quat, used for the dot product check
|
||||
const MCore::DualQuaternion& pivotQuat = mBones[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat;
|
||||
const MCore::DualQuaternion& pivotQuat = boneInfos[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat;
|
||||
|
||||
// our skinning dual quaternion
|
||||
MCore::DualQuaternion skinQuat(AZ::Quaternion(0, 0, 0, 0), AZ::Quaternion(0, 0, 0, 0));
|
||||
|
||||
for (size_t i = 0; i < numInfluences; ++i)
|
||||
{
|
||||
// get the influence
|
||||
influence = layer->GetInfluence(orgVertex, i);
|
||||
boneInfo = &mBones[ influence->GetBoneNr() ];
|
||||
weight = influence->GetWeight();
|
||||
SkinInfluence* influence = layer->GetInfluence(orgVertex, i);
|
||||
weight = influence->GetWeight();
|
||||
|
||||
// check if we need to invert the dual quat
|
||||
MCore::DualQuaternion& influenceQuat = mBones[ influence->GetBoneNr() ].mDualQuat;
|
||||
MCore::DualQuaternion influenceQuat = boneInfos[ influence->GetBoneNr() ].mDualQuat;
|
||||
if (influenceQuat.mReal.Dot(pivotQuat.mReal) < 0.0f)
|
||||
{
|
||||
influenceQuat *= -1.0f;
|
||||
@@ -249,68 +231,46 @@ namespace EMotionFX
|
||||
skinQuat.Normalize();
|
||||
|
||||
// perform skinning
|
||||
newPos = skinQuat.TransformPoint(vtxPos);
|
||||
newNormal = skinQuat.TransformVector(normal);
|
||||
newTangent = skinQuat.TransformVector(tangent);
|
||||
positions[v] = skinQuat.TransformPoint(vtxPos);
|
||||
normals[v] = skinQuat.TransformVector(normal);
|
||||
newTangent = skinQuat.TransformVector(tangent);
|
||||
tangents[v].Set(newTangent.GetX(), newTangent.GetY(), newTangent.GetZ(), tangentW);
|
||||
}
|
||||
else
|
||||
{
|
||||
// perform the skinning
|
||||
newPos = vtxPos;
|
||||
newNormal = normal;
|
||||
newTangent = tangent;
|
||||
// no skinning influences, just copy the values
|
||||
positions[v] = vtxPos;
|
||||
normals[v] = normal;
|
||||
newTangent = tangent;
|
||||
tangents[v].Set(newTangent.GetX(), newTangent.GetY(), newTangent.GetZ(), tangentW);
|
||||
}
|
||||
|
||||
// output the skinned values
|
||||
positions->Set (newPos.GetX(), newPos.GetY(), newPos.GetZ());
|
||||
positions++;
|
||||
normals->Set (newNormal.GetX(), newNormal.GetY(), newNormal.GetZ());
|
||||
normals++;
|
||||
tangents->Set (newTangent.GetX(), newTangent.GetY(), newTangent.GetZ(), tangentW);
|
||||
tangents++;
|
||||
}
|
||||
}
|
||||
else // there are no tangents and bitangents to skin
|
||||
{
|
||||
const uint32 numVertices = mMesh->GetNumVertices();
|
||||
uint32 v = 0;
|
||||
uint32 orgVertex;
|
||||
|
||||
SkinInfluence* influence;
|
||||
BoneInfo* boneInfo;
|
||||
float weight;
|
||||
|
||||
for (v = 0; v < numVertices; ++v)
|
||||
for (AZ::u32 v = startVertex; v < endVertex; ++v)
|
||||
{
|
||||
// get the original vertex number
|
||||
orgVertex = *(orgVerts++);
|
||||
|
||||
// reset the skinned position
|
||||
newPos = AZ::Vector3::CreateZero();
|
||||
newNormal = AZ::Vector3::CreateZero();
|
||||
|
||||
vtxPos.Set(positions->GetX(), positions->GetY(), positions->GetZ());
|
||||
normal.Set(normals->GetX(), normals->GetY(), normals->GetZ());
|
||||
orgVertex = orgVerts[v];
|
||||
vtxPos = positions[v];
|
||||
normal = normals[v];
|
||||
|
||||
// process the skin influences for this vertex
|
||||
const size_t numInfluences = layer->GetNumInfluences(orgVertex);
|
||||
if (numInfluences > 0)
|
||||
{
|
||||
// get the pivot quat, used for the dot product check
|
||||
const MCore::DualQuaternion& pivotQuat = mBones[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat;
|
||||
const MCore::DualQuaternion& pivotQuat = boneInfos[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat;
|
||||
|
||||
// our skinning dual quaternion
|
||||
MCore::DualQuaternion skinQuat(AZ::Quaternion(0, 0, 0, 0), AZ::Quaternion(0, 0, 0, 0));
|
||||
|
||||
for (size_t i = 0; i < numInfluences; ++i)
|
||||
{
|
||||
// get the influence
|
||||
influence = layer->GetInfluence(orgVertex, i);
|
||||
boneInfo = &mBones[ influence->GetBoneNr() ];
|
||||
weight = influence->GetWeight();
|
||||
SkinInfluence* influence = layer->GetInfluence(orgVertex, i);
|
||||
weight = influence->GetWeight();
|
||||
|
||||
// check if we need to invert the dual quat
|
||||
MCore::DualQuaternion& influenceQuat = mBones[ influence->GetBoneNr() ].mDualQuat;
|
||||
MCore::DualQuaternion influenceQuat = boneInfos[ influence->GetBoneNr() ].mDualQuat;
|
||||
if (influenceQuat.mReal.Dot(pivotQuat.mReal) < 0.0f)
|
||||
{
|
||||
influenceQuat *= -1.0f;
|
||||
@@ -324,26 +284,19 @@ namespace EMotionFX
|
||||
skinQuat.Normalize();
|
||||
|
||||
// perform skinning
|
||||
newPos = skinQuat.TransformPoint(vtxPos);
|
||||
newNormal = skinQuat.TransformVector(normal);
|
||||
positions[v] = skinQuat.TransformPoint(vtxPos);
|
||||
normals[v] = skinQuat.TransformVector(normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
// perform the skinning
|
||||
newPos = vtxPos;
|
||||
newNormal = normal;
|
||||
// no skinning influences, just copy the values
|
||||
positions[v] = vtxPos;
|
||||
normals[v] = normal;
|
||||
}
|
||||
|
||||
// output the skinned values
|
||||
positions->Set(newPos.GetX(), newPos.GetY(), newPos.GetZ());
|
||||
positions++;
|
||||
normals->Set(newNormal.GetX(), newNormal.GetY(), newNormal.GetZ());
|
||||
normals++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// initialize the mesh deformer
|
||||
void DualQuatSkinDeformer::Reinitialize(Actor* actor, Node* node, uint32 lodLevel)
|
||||
{
|
||||
@@ -352,7 +305,7 @@ namespace EMotionFX
|
||||
MCORE_UNUSED(lodLevel);
|
||||
|
||||
// clear the bone information array, but don't free the currently allocated/reserved memory
|
||||
mBones.Clear(false);
|
||||
m_bones.clear();
|
||||
|
||||
// if there is no mesh
|
||||
if (mMesh == nullptr)
|
||||
@@ -360,13 +313,9 @@ namespace EMotionFX
|
||||
return;
|
||||
}
|
||||
|
||||
// get the attribute number
|
||||
SkinningInfoVertexAttributeLayer* skinningLayer = (SkinningInfoVertexAttributeLayer*)mMesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID);
|
||||
MCORE_ASSERT(skinningLayer);
|
||||
|
||||
// reserve space for the bone array
|
||||
//mBones.Reserve( actor->GetNumNodes() );
|
||||
|
||||
// find out what bones this mesh uses
|
||||
const uint32 numOrgVerts = mMesh->GetNumOrgVertices();
|
||||
for (uint32 i = 0; i < numOrgVerts; i++)
|
||||
@@ -379,26 +328,21 @@ namespace EMotionFX
|
||||
{
|
||||
SkinInfluence* influence = skinningLayer->GetInfluence(i, a);
|
||||
|
||||
// get the bone index in the array
|
||||
uint32 boneIndex = FindLocalBoneIndex(influence->GetNodeNr());
|
||||
|
||||
// if the bone is not found in our array
|
||||
if (boneIndex == MCORE_INVALIDINDEX32)
|
||||
AZ::Outcome<size_t> boneIndexOutcome = FindLocalBoneIndex(influence->GetNodeNr());
|
||||
if (boneIndexOutcome.IsSuccess())
|
||||
{
|
||||
influence->SetBoneNr(boneIndexOutcome.GetValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
// add the bone to the array of bones in this deformer
|
||||
mBones.AddEmptyExact();
|
||||
BoneInfo& lastBone = mBones.GetLast();
|
||||
BoneInfo lastBone;
|
||||
lastBone.mNodeNr = influence->GetNodeNr();
|
||||
lastBone.mDualQuat.Identity();
|
||||
boneIndex = mBones.GetLength() - 1;
|
||||
m_bones.emplace_back(lastBone);
|
||||
influence->SetBoneNr(static_cast<AZ::u16>(m_bones.size() - 1));
|
||||
}
|
||||
|
||||
// set the bone number in the influence
|
||||
influence->SetBoneNr(static_cast<uint16>(boneIndex));
|
||||
}
|
||||
}
|
||||
|
||||
// get rid of all items in the used bones array
|
||||
// mBones.Shrink();
|
||||
}
|
||||
} // namespace EMotionFX
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// include the required headers
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/Outcome/Outcome.h>
|
||||
#include "EMotionFXConfig.h"
|
||||
#include <MCore/Source/DualQuaternion.h>
|
||||
#include "Mesh.h"
|
||||
#include "MeshDeformer.h"
|
||||
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
// forward declarations
|
||||
@@ -101,37 +101,47 @@ namespace EMotionFX
|
||||
* This is the number of different bones that the skinning information of the mesh where this deformer works on uses.
|
||||
* @result The number of bones.
|
||||
*/
|
||||
MCORE_INLINE uint32 GetNumLocalBones() const { return mBones.GetLength(); }
|
||||
MCORE_INLINE uint32 GetNumLocalBones() const { return static_cast<uint32>(m_bones.size()); }
|
||||
|
||||
/**
|
||||
* Get the node number of a given local bone.
|
||||
* @param index The local bone number, which must be in range of [0..GetNumLocalBones()-1].
|
||||
* @result The node number, which is in range of [0..Actor::GetNumNodes()-1], depending on the actor where this deformer works on.
|
||||
*/
|
||||
MCORE_INLINE uint32 GetLocalBone(uint32 index) const { return mBones[index].mNodeNr; }
|
||||
MCORE_INLINE uint32 GetLocalBone(uint32 index) const { return m_bones[index].mNodeNr; }
|
||||
|
||||
/**
|
||||
* Pre-allocate space for a given number of local bones.
|
||||
* This does not alter the value returned by GetNumLocalBones().
|
||||
* @param numBones The number of bones to pre-allocate space for.
|
||||
*/
|
||||
MCORE_INLINE void ReserveLocalBones(uint32 numBones) { mBones.Reserve(numBones); }
|
||||
|
||||
MCORE_INLINE void ReserveLocalBones(uint32 numBones) { m_bones.reserve(numBones); }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Structure used for precalculating the skinning matrices.
|
||||
* Structure used for pre-calculating the skinning matrices.
|
||||
*/
|
||||
struct EMFX_API BoneInfo
|
||||
{
|
||||
uint32 mNodeNr; /**< The node number. */
|
||||
MCore::DualQuaternion mDualQuat; /**< The dual quat of the precalculated matrix that contains the "globalMatrix * inverse(bindPoseMatrix)". */
|
||||
MCore::DualQuaternion mDualQuat; /**< The dual quat of the pre-calculated matrix that contains the "globalMatrix * inverse(bindPoseMatrix)". */
|
||||
|
||||
MCORE_INLINE BoneInfo()
|
||||
: mNodeNr(MCORE_INVALIDINDEX32) {}
|
||||
};
|
||||
AZStd::vector<BoneInfo> m_bones; /**< The array of bone information used for pre-calculation. */
|
||||
|
||||
MCore::Array<BoneInfo> mBones; /**< The array of bone information used for precalculation. */
|
||||
/**
|
||||
* Skin a part of the mesh.
|
||||
* @param mesh The mesh to be skinned.
|
||||
* @param startVertex The start vertex index to start skinning.
|
||||
* @param endVertex The end vertex index for the range to be skinned.
|
||||
* @param boneInfos The pre-calculated skinning matrices shared across the skinning process.
|
||||
*/
|
||||
static void SkinRange(Mesh* mesh, AZ::u32 startVertex, AZ::u32 endVertex, const AZStd::vector<BoneInfo>& boneInfos);
|
||||
|
||||
//! Number of vertices per batch/job used for multi-threaded software skinning.
|
||||
static constexpr AZ::u32 s_numVerticesPerBatch = 10000;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
@@ -149,18 +159,6 @@ namespace EMotionFX
|
||||
* @param nodeIndex The node number to search for.
|
||||
* @result The index inside the mBones member array, which uses the given node.
|
||||
*/
|
||||
MCORE_INLINE uint32 FindLocalBoneIndex(uint32 nodeIndex) const
|
||||
{
|
||||
const uint32 numBones = mBones.GetLength();
|
||||
for (uint32 i = 0; i < numBones; ++i)
|
||||
{
|
||||
if (mBones[i].mNodeNr == nodeIndex)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return MCORE_INVALIDINDEX32;
|
||||
}
|
||||
AZ::Outcome<size_t> FindLocalBoneIndex(uint32 nodeIndex) const;
|
||||
};
|
||||
} // namespace EMotionFX
|
||||
|
||||
+26
-13
@@ -21,6 +21,7 @@
|
||||
#include <EMotionFX/Source/Motion.h>
|
||||
#include <EMotionFX/Source/EMotionFXManager.h>
|
||||
#include <EMotionFX/CommandSystem/Source/CommandManager.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
|
||||
#include <QSettings>
|
||||
#include <QGridLayout>
|
||||
@@ -398,33 +399,49 @@ namespace EMStudio
|
||||
const size_t numDirtyFiles = dirtyFileNames.size();
|
||||
mTableWidget->setRowCount(static_cast<int>(numDirtyFiles));
|
||||
|
||||
AZStd::string extension, typeString, filenameText, path, filenameOnly;
|
||||
for (size_t i = 0; i < numDirtyFiles; ++i)
|
||||
{
|
||||
SaveDirtyFilesCallback::ObjectPointer object = mObjects[i];
|
||||
|
||||
QString labelText;
|
||||
if (dirtyFileNames[i].empty())
|
||||
{
|
||||
filenameText = "<not saved yet>";
|
||||
labelText = "<not saved yet>";
|
||||
}
|
||||
else
|
||||
{
|
||||
AzFramework::StringFunc::Path::GetFullPath(dirtyFileNames[i].c_str(), path);
|
||||
AzFramework::StringFunc::Path::GetFullFileName(dirtyFileNames[i].c_str(), filenameOnly);
|
||||
const AZStd::string& productFilename = dirtyFileNames[i];
|
||||
|
||||
filenameText = AZStd::string::format("<qt>%s<b>%s</b></qt>", path.c_str(), filenameOnly.c_str());
|
||||
// Get the asset source name from the product filename.
|
||||
bool sourceAssetFound = false;
|
||||
AZStd::string sourceAssetFilename;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceAssetFound,
|
||||
&AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath,
|
||||
productFilename,
|
||||
sourceAssetFilename);
|
||||
|
||||
const AZStd::string usedFilename = sourceAssetFound ? sourceAssetFilename : dirtyFileNames[i];
|
||||
|
||||
// Separate the path from the filename, so that we can display the filename in bold.
|
||||
AZStd::string fullPath;
|
||||
AzFramework::StringFunc::Path::GetFullPath(usedFilename.c_str(), fullPath);
|
||||
AzFramework::StringFunc::RelativePath::Normalize(fullPath); // Add trailing slash in case it is missing
|
||||
AZStd::string fullFilename;
|
||||
AzFramework::StringFunc::Path::GetFullFileName(usedFilename.c_str(), fullFilename);
|
||||
labelText = QString("<qt>%1<b>%2</b></qt>").arg(fullPath.c_str(), fullFilename.c_str());
|
||||
}
|
||||
|
||||
// create the checkbox
|
||||
QCheckBox* checkbox = new QCheckBox("");
|
||||
checkbox->setStyleSheet("background: transparent; padding-left: 3px; max-width: 13px;");
|
||||
checkbox->setStyleSheet("background: transparent;");
|
||||
checkbox->setChecked(true);
|
||||
|
||||
// create the filename table item
|
||||
QLabel* filenameLabel = new QLabel();
|
||||
filenameLabel->setToolTip(filenameText.c_str());
|
||||
filenameLabel->setText(filenameText.c_str());
|
||||
filenameLabel->setToolTip(labelText);
|
||||
filenameLabel->setText(labelText);
|
||||
|
||||
QString typeString;
|
||||
if (object.mMotion)
|
||||
{
|
||||
typeString = "Motion";
|
||||
@@ -445,12 +462,8 @@ namespace EMStudio
|
||||
{
|
||||
typeString = "Workspace";
|
||||
}
|
||||
else
|
||||
{
|
||||
typeString = "";
|
||||
}
|
||||
|
||||
QTableWidgetItem* itemType = new QTableWidgetItem(typeString.c_str());
|
||||
QTableWidgetItem* itemType = new QTableWidgetItem(typeString);
|
||||
const int row = static_cast<int>(i);
|
||||
itemType->setData(Qt::UserRole, row);
|
||||
|
||||
|
||||
@@ -650,7 +650,6 @@ namespace EMotionFX
|
||||
}
|
||||
|
||||
distance = std::numeric_limits<float>::max();
|
||||
bool isHit = false;
|
||||
|
||||
// Get the MCore::Ray used by Mesh::Intersects
|
||||
// Convert the input source position and direction to a line segment by using the frustum depth as line length.
|
||||
@@ -659,12 +658,13 @@ namespace EMotionFX
|
||||
const AZ::Vector3 dest = src + dir * frustumDepth;
|
||||
const MCore::Ray ray(src, dest);
|
||||
|
||||
// Update the mesh deformers so the intersection test will hit the actor if it is being
|
||||
// animated by a motion component that is previewing the animation in the editor
|
||||
// Update the mesh deformers (apply software skinning and morphing) so the intersection test will hit the actor
|
||||
// if it is being animated by a motion component that is previewing the animation in the editor.
|
||||
m_actorInstance->UpdateMeshDeformers(0.0f, true);
|
||||
|
||||
const TransformData* transformData = m_actorInstance->GetTransformData();
|
||||
const Pose* currentPose = transformData->GetCurrentPose();
|
||||
bool isHit = false;
|
||||
|
||||
// Iterate through the meshes in the actor, looking for the closest hit
|
||||
const AZ::u32 lodLevel = m_actorInstance->GetLODLevel();
|
||||
|
||||
@@ -115,11 +115,13 @@ static int Create2DTexture(int width, int height, byte* data, ETEX_Format format
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
static AZ::Vector2 GetTextureSize(AZ::Data::Instance<AZ::RPI::Image> image)
|
||||
{
|
||||
AZ::RHI::Size size = image->GetDescriptor().m_size;
|
||||
return AZ::Vector2(size.m_width, size.m_height);
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(_RELEASE)
|
||||
|
||||
@@ -312,7 +312,7 @@ class Validator(object):
|
||||
# Once we split the repos we will have to worry about multiple root points etc. but that is a problem for future us.
|
||||
# All the packaging safelist stuff goes away once repo is split for platforms
|
||||
this_path = Path(__file__).resolve()
|
||||
root_folder = this_path.parents[5]
|
||||
root_folder = this_path.parents[2]
|
||||
relative_folder = os.path.relpath(this_path.parent, root_folder)
|
||||
canary_file = os.path.join(root_folder, 'restricted', platform, relative_folder, platform.lower() + '_canary.txt')
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user