Merge branch 'development' into profiler_capture_api
Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com>
This commit is contained in:
@@ -65,8 +65,35 @@ namespace AZ
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides - Application is a singleton
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
typedef AZStd::recursive_mutex MutexType;
|
||||
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
|
||||
static constexpr bool EnableEventQueue = true;
|
||||
using EventQueueMutexType = AZStd::mutex;
|
||||
struct PostThreadDispatchInvoker
|
||||
{
|
||||
~PostThreadDispatchInvoker();
|
||||
};
|
||||
|
||||
template <typename DispatchMutex>
|
||||
struct ThreadDispatchLockGuard
|
||||
{
|
||||
ThreadDispatchLockGuard(DispatchMutex& contextMutex)
|
||||
: m_lock{ contextMutex }
|
||||
{}
|
||||
ThreadDispatchLockGuard(DispatchMutex& contextMutex, AZStd::adopt_lock_t adopt_lock)
|
||||
: m_lock{ contextMutex, adopt_lock }
|
||||
{}
|
||||
ThreadDispatchLockGuard(const ThreadDispatchLockGuard&) = delete;
|
||||
ThreadDispatchLockGuard& operator=(const ThreadDispatchLockGuard&) = delete;
|
||||
private:
|
||||
PostThreadDispatchInvoker m_threadPolicyInvoker;
|
||||
using LockType = AZStd::conditional_t<LocklessDispatch, AZ::Internal::NullLockGuard<DispatchMutex>, AZStd::scoped_lock<DispatchMutex>>;
|
||||
LockType m_lock;
|
||||
};
|
||||
|
||||
template <typename DispatchMutex, bool>
|
||||
using DispatchLockGuard = ThreadDispatchLockGuard<DispatchMutex>;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ~AssetCatalogRequests() = default;
|
||||
@@ -200,6 +227,17 @@ namespace AZ
|
||||
|
||||
using AssetCatalogRequestBus = AZ::EBus<AssetCatalogRequests>;
|
||||
|
||||
inline AssetCatalogRequests::PostThreadDispatchInvoker::~PostThreadDispatchInvoker()
|
||||
{
|
||||
if (!AssetCatalogRequestBus::IsInDispatchThisThread())
|
||||
{
|
||||
if (AssetCatalogRequestBus::QueuedEventCount())
|
||||
{
|
||||
AssetCatalogRequestBus::ExecuteQueuedEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Events that AssetManager listens for
|
||||
*/
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <AzCore/Casting/lossy_cast.h>
|
||||
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/Component/ComponentApplicationLifecycle.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
|
||||
#include <AzCore/Debug/LocalFileEventLogger.h>
|
||||
@@ -44,8 +45,6 @@
|
||||
#include <AzCore/Module/Module.h>
|
||||
#include <AzCore/Module/ModuleManager.h>
|
||||
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/Path/Path_fwd.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
|
||||
#include <AzCore/Driller/Driller.h>
|
||||
@@ -506,6 +505,16 @@ namespace AZ
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*m_settingsRegistry);
|
||||
|
||||
// The /O3DE/Application/LifecycleEvents array contains a valid set of lifecycle events
|
||||
// Those lifecycle events are normally read from the <engine-root>/Registry
|
||||
// which isn't merged until ComponentApplication::Create invokes MergeSettingsToRegistry
|
||||
// So pre-populate the valid lifecycle even entries
|
||||
ComponentApplicationLifecycle::RegisterEvent(*m_settingsRegistry, "SystemAllocatorCreated");
|
||||
ComponentApplicationLifecycle::RegisterEvent(*m_settingsRegistry, "SettingsRegistryAvailable");
|
||||
ComponentApplicationLifecycle::RegisterEvent(*m_settingsRegistry, "ConsoleAvailable");
|
||||
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "SystemAllocatorCreated", R"({})");
|
||||
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "SettingsRegistryAvailable", R"({})");
|
||||
|
||||
// Create the Module Manager
|
||||
m_moduleManager = AZStd::make_unique<ModuleManager>();
|
||||
|
||||
@@ -520,6 +529,7 @@ namespace AZ
|
||||
m_ownsConsole = true;
|
||||
m_console->LinkDeferredFunctors(AZ::ConsoleFunctorBase::GetDeferredHead());
|
||||
m_settingsRegistryConsoleFunctors = AZ::SettingsRegistryConsoleUtils::RegisterAzConsoleCommands(*m_settingsRegistry, *m_console);
|
||||
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "ConsoleAvailable", R"({})");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,6 +561,7 @@ namespace AZ
|
||||
{
|
||||
AZ::Interface<AZ::IConsole>::Unregister(m_console);
|
||||
delete m_console;
|
||||
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "ConsoleUnavailable", R"({})");
|
||||
}
|
||||
|
||||
m_moduleManager.reset();
|
||||
@@ -558,6 +569,8 @@ namespace AZ
|
||||
if (AZ::SettingsRegistry::Get() == m_settingsRegistry.get())
|
||||
{
|
||||
SettingsRegistry::Unregister(m_settingsRegistry.get());
|
||||
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "SettingsRegistryUnavailable", R"({})");
|
||||
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "SystemAllocatorPendingDestruction", R"({})");
|
||||
}
|
||||
m_settingsRegistry.reset();
|
||||
|
||||
@@ -672,6 +685,8 @@ namespace AZ
|
||||
ReflectionEnvironment::GetReflectionManager()->Reflect(azrtti_typeid(this), [this](ReflectContext* context) {Reflect(context); });
|
||||
|
||||
RegisterCoreComponents();
|
||||
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "ReflectionManagerAvailable", R"({})");
|
||||
|
||||
TickBus::AllowFunctionQueuing(true);
|
||||
SystemTickBus::AllowFunctionQueuing(true);
|
||||
|
||||
@@ -691,6 +706,7 @@ namespace AZ
|
||||
|
||||
// Load the actual modules
|
||||
LoadModules();
|
||||
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "GemsLoaded", R"({})");
|
||||
|
||||
// Execute user.cfg after modules have been loaded but before processing any command-line overrides
|
||||
AZ::IO::FixedMaxPath platformCachePath;
|
||||
@@ -756,12 +772,14 @@ namespace AZ
|
||||
m_entities.rehash(0); // force free all memory
|
||||
|
||||
DestroyReflectionManager();
|
||||
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "ReflectionManagerUnavailable", R"({})");
|
||||
|
||||
static_cast<SettingsRegistryImpl*>(m_settingsRegistry.get())->ClearNotifiers();
|
||||
static_cast<SettingsRegistryImpl*>(m_settingsRegistry.get())->ClearMergeEvents();
|
||||
|
||||
// Uninit and unload any dynamic modules.
|
||||
m_moduleManager->UnloadModules();
|
||||
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "GemsUnloaded", R"({})");
|
||||
|
||||
NameDictionary::Destroy();
|
||||
|
||||
|
||||
@@ -175,6 +175,8 @@ namespace AZ
|
||||
bool m_loadDynamicModules = true;
|
||||
//! Used by test fixtures to ensure reflection occurs to edit context.
|
||||
bool m_createEditContext = false;
|
||||
//! Indicates whether the AssetCatalog.xml should be loaded by default in Application::StartCommon
|
||||
bool m_loadAssetCatalog = true;
|
||||
};
|
||||
|
||||
ComponentApplication();
|
||||
@@ -356,7 +358,7 @@ namespace AZ
|
||||
/// Calculates the root directory of the engine.
|
||||
void CalculateEngineRoot();
|
||||
|
||||
/// Calculates the directory where the bootstrap.cfg file resides.
|
||||
/// Deprecated: The term "AppRoot" has no meaning
|
||||
void CalculateAppRoot();
|
||||
|
||||
template<typename Iterator>
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Component/ComponentApplicationLifecycle.h>
|
||||
#include <AzCore/Settings/SettingsRegistryVisitorUtils.h>
|
||||
|
||||
namespace AZ::ComponentApplicationLifecycle
|
||||
{
|
||||
bool ValidateEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName)
|
||||
{
|
||||
using FixedValueString = SettingsRegistryInterface::FixedValueString;
|
||||
using Type = SettingsRegistryInterface::Type;
|
||||
FixedValueString eventRegistrationKey{ ApplicationLifecycleEventRegistrationKey };
|
||||
eventRegistrationKey += '/';
|
||||
eventRegistrationKey += eventName;
|
||||
return settingsRegistry.GetType(eventRegistrationKey) == Type::Object;
|
||||
}
|
||||
|
||||
bool SignalEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName, AZStd::string_view eventValue)
|
||||
{
|
||||
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
|
||||
using Format = AZ::SettingsRegistryInterface::Format;
|
||||
|
||||
if (!ValidateEvent(settingsRegistry, eventName))
|
||||
{
|
||||
AZ_Warning("ComponentApplicationLifecycle", false, R"(Cannot signal event %.*s. Name does is not a field of object "%.*s".)"
|
||||
R"( Please make sure the entry exists in the '<engine-root>/Registry/application_lifecycle_events.setreg")"
|
||||
" or in *.setreg within the project", AZ_STRING_ARG(eventName), AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey));
|
||||
return false;
|
||||
}
|
||||
auto eventRegistrationKey = FixedValueString::format("%.*s/%.*s", AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey),
|
||||
AZ_STRING_ARG(eventName));
|
||||
|
||||
return settingsRegistry.MergeSettings(eventValue, Format::JsonMergePatch, eventRegistrationKey);
|
||||
}
|
||||
|
||||
bool RegisterEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName)
|
||||
{
|
||||
using FixedValueString = SettingsRegistryInterface::FixedValueString;
|
||||
using Format = AZ::SettingsRegistryInterface::Format;
|
||||
|
||||
if (!ValidateEvent(settingsRegistry, eventName))
|
||||
{
|
||||
FixedValueString eventRegistrationKey{ ApplicationLifecycleEventRegistrationKey };
|
||||
eventRegistrationKey += '/';
|
||||
eventRegistrationKey += eventName;
|
||||
return settingsRegistry.MergeSettings(R"({})", Format::JsonMergePatch, eventRegistrationKey);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegisterHandler(AZ::SettingsRegistryInterface& settingsRegistry, AZ::SettingsRegistryInterface::NotifyEventHandler& handler,
|
||||
AZ::SettingsRegistryInterface::NotifyCallback callback, AZStd::string_view eventName)
|
||||
{
|
||||
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
|
||||
using Type = AZ::SettingsRegistryInterface::Type;
|
||||
using NotifyEventHandler = AZ::SettingsRegistryInterface::NotifyEventHandler;
|
||||
|
||||
if (!ValidateEvent(settingsRegistry, eventName))
|
||||
{
|
||||
AZ_Warning("ComponentApplicationLifecycle", false, R"(Cannot register event %.*s. Name does is not a field of object "%.*s".)"
|
||||
R"( Please make sure the entry exists in the '<engine-root>/Registry/application_lifecycle_events.setreg")"
|
||||
" or in *.setreg within the project", AZ_STRING_ARG(eventName), AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey));
|
||||
return false;
|
||||
}
|
||||
auto eventNameRegistrationKey = FixedValueString::format("%.*s/%.*s", AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey),
|
||||
AZ_STRING_ARG(eventName));
|
||||
auto lifecycleCallback = [callback = AZStd::move(callback), eventNameRegistrationKey](AZStd::string_view path, Type type)
|
||||
{
|
||||
if (path == eventNameRegistrationKey)
|
||||
{
|
||||
callback(path, type);
|
||||
}
|
||||
};
|
||||
|
||||
handler = NotifyEventHandler(AZStd::move(lifecycleCallback));
|
||||
settingsRegistry.RegisterNotifier(handler);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
|
||||
namespace AZ::ComponentApplicationLifecycle
|
||||
{
|
||||
//! Root Key where lifecycle events should be registered under
|
||||
inline constexpr AZStd::string_view ApplicationLifecycleEventRegistrationKey = "/O3DE/Runtime/Application/LifecycleEvents";
|
||||
|
||||
|
||||
//! Validates that the event @eventName is stored in the array at ApplicationLifecycleEventRegistrationKey
|
||||
//! @param settingsRegistry registry where @eventName will be searched
|
||||
//! @param eventName name of key that validated that exists as an element in the ApplicationLifecycleEventRegistrationKey array
|
||||
//! @return true if the @eventName was found in the ApplicationLifecycleEventRegistrationKey array
|
||||
bool ValidateEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName);
|
||||
|
||||
//! Wrapper around setting a value underneath the ApplicationLifecycleEventRegistrationKey
|
||||
//! It validates if the @eventName is is part of the ApplicationLifecycleEventRegistrationKey array
|
||||
//! It then appends the @eventName to the ApplicationLifecycleEventRegistrationKey merges the @eventValue into
|
||||
//! the SettingsRegistry at that key
|
||||
//! NOTE: This function should only be invoked from ComponentApplication and its derived classes
|
||||
//! @param settingsRegistry registry where eventName should be set
|
||||
//! @param eventName name of key underneath the ApplicationLifecycleEventRegistrationKey to signal
|
||||
//! @param eventValue JSON Object that will be merged into the SettingsRegistry at <ApplicationLifecycleEventRootKey>/<eventName>
|
||||
//! @return true if the eventValue was successfully merged at the <ApplicationLifecycleEventRootKey>/<eventName>
|
||||
bool SignalEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName, AZStd::string_view eventValue);
|
||||
|
||||
//! Register that the event @eventName is stored in the array at ApplicationLifecycleEventRegistrationKey
|
||||
//! @param settingsRegistry registry where @eventName will be searched
|
||||
//! @param eventName name of key that will be stored in the ApplicationLifecycleEventRegistrationKey array
|
||||
//! @return true if the event passed validation or the eventName was stored in the ApplicationLifecycleEventRegistrationKey array
|
||||
bool RegisterEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName);
|
||||
|
||||
//! Wrapper around registering the NotifyEventHandler with the SettingsRegistry for the specified event
|
||||
//! It validates if the @eventName is is part of the ApplicationLifecycleEventRegistrationKey array and if
|
||||
//! so moves the @callback into @handler and then registers the handler with the SettingsRegistry NotifyEvent
|
||||
//! @param settingsRegistry registry where handler will be registered
|
||||
//! @param handler handler where callback will be moved into and then registered with the SettingsRegistry
|
||||
//! if the specified @eventName passes validation
|
||||
//! @param callback will be moved into the handler if the specified @eventName is valid
|
||||
//! @param eventName name of key underneath the ApplicationLifecycleEventRegistrationKey to register
|
||||
//! @return true if the handler was registered with the SettingsRegistry NotifyEvent
|
||||
bool RegisterHandler(AZ::SettingsRegistryInterface& settingsRegistry, AZ::SettingsRegistryInterface::NotifyEventHandler& handler,
|
||||
AZ::SettingsRegistryInterface::NotifyCallback callback, AZStd::string_view eventName);
|
||||
}
|
||||
@@ -262,6 +262,6 @@ static constexpr AZ::ThreadSafety ConsoleThreadSafety<_TYPE, std::enable_if_t<st
|
||||
//! @param _FLAGS a set of AzFramework::ConsoleFunctorFlags used to mutate behaviour
|
||||
//! @param _DESC a description of the cvar
|
||||
#define AZ_CONSOLEFREEFUNC_4(_NAME, _FUNCTION, _FLAGS, _DESC) \
|
||||
inline AZ::ConsoleFunctor<void, false> Functor##_FUNCTION(#_FUNCTION, _DESC, _FLAGS | AZ::ConsoleFunctorFlags::DontDuplicate, AZ::TypeId::CreateNull(), &_FUNCTION)
|
||||
inline AZ::ConsoleFunctor<void, false> Functor##_FUNCTION(_NAME, _DESC, _FLAGS | AZ::ConsoleFunctorFlags::DontDuplicate, AZ::TypeId::CreateNull(), &_FUNCTION)
|
||||
|
||||
#define AZ_CONSOLEFREEFUNC(...) AZ_MACRO_SPECIALIZE(AZ_CONSOLEFREEFUNC_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
|
||||
|
||||
@@ -10,16 +10,13 @@
|
||||
#include <AzCore/Module/Internal/ModuleManagerSearchPathTool.h>
|
||||
|
||||
#include <AzCore/Module/Module.h>
|
||||
#include <AzCore/RTTI/AttributeReader.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/ComponentApplicationLifecycle.h>
|
||||
#include <AzCore/NativeUI/NativeUIRequests.h>
|
||||
#include <AzCore/Script/ScriptSystemBus.h>
|
||||
#include <AzCore/Script/ScriptContext.h>
|
||||
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
@@ -221,11 +218,16 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string componentNamesArray = R"({ "SystemComponents":[)";
|
||||
const char* comma = "";
|
||||
// For all system components, deactivate
|
||||
for (auto componentIt = m_systemComponents.rbegin(); componentIt != m_systemComponents.rend(); ++componentIt)
|
||||
{
|
||||
ModuleEntity::DeactivateComponent(**componentIt);
|
||||
componentNamesArray += AZStd::string::format(R"(%s"%s")", comma, (*componentIt)->RTTI_GetTypeName());
|
||||
comma = ", ";
|
||||
}
|
||||
componentNamesArray += R"(]})";
|
||||
|
||||
// For all modules that we created an entity for, set them to "Init" (meaning not Activated)
|
||||
for (auto& moduleData : m_ownedModules)
|
||||
@@ -239,6 +241,13 @@ namespace AZ
|
||||
|
||||
// Since the system components have been deactivated clear out the vector.
|
||||
m_systemComponents.clear();
|
||||
|
||||
// Signal that the System Components have deactivated
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
AZ::ComponentApplicationLifecycle::SignalEvent(*settingsRegistry, "SystemComponentsDeactivated", componentNamesArray);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -284,7 +293,11 @@ namespace AZ
|
||||
{
|
||||
// Split the tag list
|
||||
AZStd::vector<AZStd::string_view> tagList;
|
||||
AZStd::tokenize<AZStd::string_view>(tags, ",", tagList);
|
||||
auto TokenizeTags = [&tagList](AZStd::string_view token)
|
||||
{
|
||||
tagList.push_back(token);
|
||||
};
|
||||
AZ::StringFunc::TokenizeVisitor(tags, TokenizeTags, ',');
|
||||
|
||||
m_systemComponentTags.resize(tagList.size());
|
||||
AZStd::transform(tagList.begin(), tagList.end(), m_systemComponentTags.begin(), [](const AZStd::string_view& tag)
|
||||
@@ -737,11 +750,17 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string componentNamesArray = R"({ "SystemComponents":[)";
|
||||
const char* comma = "";
|
||||
// Activate the entities in the appropriate order
|
||||
for (Component* component : componentsToActivate)
|
||||
{
|
||||
ModuleEntity::ActivateComponent(*component);
|
||||
|
||||
componentNamesArray += AZStd::string::format(R"(%s"%s")", comma, component->RTTI_GetTypeName());
|
||||
comma = ", ";
|
||||
}
|
||||
componentNamesArray += R"(]})";
|
||||
|
||||
// Done activating; set state to active
|
||||
for (auto& moduleData : modulesToInit)
|
||||
@@ -755,5 +774,12 @@ namespace AZ
|
||||
|
||||
// Save the activated components for deactivation later
|
||||
m_systemComponents.insert(m_systemComponents.end(), componentsToActivate.begin(), componentsToActivate.end());
|
||||
|
||||
// Signal that the System Components are activated
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
AZ::ComponentApplicationLifecycle::SignalEvent(*settingsRegistry, "SystemComponentsActivated",
|
||||
componentNamesArray);
|
||||
}
|
||||
}
|
||||
} // namespace AZ
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
|
||||
namespace AZ::SettingsRegistryScriptUtils::Internal
|
||||
{
|
||||
static void RegisterScriptProxyForNotify(SettingsRegistryScriptProxy& settingsRegistryProxy)
|
||||
static void RegisterScriptProxyForNotify(SettingsRegistryInterface* settingsRegistry,
|
||||
SettingsRegistryScriptProxy::NotifyEventProxy* notifyEventProxy)
|
||||
{
|
||||
if (settingsRegistryProxy.IsValid())
|
||||
if (settingsRegistry != nullptr)
|
||||
{
|
||||
auto ForwardSettingsUpdateToProxyEvent = [&settingsRegistryProxy](AZStd::string_view path, AZ::SettingsRegistryInterface::Type)
|
||||
auto ForwardSettingsUpdateToProxyEvent = [notifyEventProxy](AZStd::string_view path, AZ::SettingsRegistryInterface::Type)
|
||||
{
|
||||
if (settingsRegistryProxy.m_notifyEventProxy)
|
||||
if (notifyEventProxy)
|
||||
{
|
||||
settingsRegistryProxy.m_notifyEventProxy->m_scriptNotifyEvent.Signal(path);
|
||||
notifyEventProxy->m_scriptNotifyEvent.Signal(path);
|
||||
}
|
||||
};
|
||||
// Register the forwarding function with the BehaviorContext
|
||||
settingsRegistryProxy.m_notifyEventProxy->m_settingsUpdatedHandler =
|
||||
settingsRegistryProxy.m_settingsRegistry->RegisterNotifier(ForwardSettingsUpdateToProxyEvent);
|
||||
notifyEventProxy->m_settingsUpdatedHandler = settingsRegistry->RegisterNotifier(ForwardSettingsUpdateToProxyEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace AZ::SettingsRegistryScriptUtils::Internal
|
||||
: m_settingsRegistry(AZStd::move(settingsRegistry))
|
||||
, m_notifyEventProxy(AZStd::make_shared<NotifyEventProxy>())
|
||||
{
|
||||
RegisterScriptProxyForNotify(*this);
|
||||
RegisterScriptProxyForNotify(m_settingsRegistry.get(), m_notifyEventProxy.get());
|
||||
}
|
||||
|
||||
// Raw AZ::SettingsRegistryInterface pointer is not owned by the proxy, so it's deleter is a no-op
|
||||
@@ -45,7 +45,7 @@ namespace AZ::SettingsRegistryScriptUtils::Internal
|
||||
: m_settingsRegistry(settingsRegistry, [](AZ::SettingsRegistryInterface*) {})
|
||||
, m_notifyEventProxy(AZStd::make_shared<NotifyEventProxy>())
|
||||
{
|
||||
RegisterScriptProxyForNotify(*this);
|
||||
RegisterScriptProxyForNotify(m_settingsRegistry.get(), m_notifyEventProxy.get());
|
||||
}
|
||||
|
||||
// SettingsRegistryScriptProxy function that determines if the SettingsRegistry object is valid
|
||||
|
||||
@@ -41,6 +41,8 @@ set(FILES
|
||||
Component/ComponentApplication.cpp
|
||||
Component/ComponentApplication.h
|
||||
Component/ComponentApplicationBus.h
|
||||
Component/ComponentApplicationLifecycle.cpp
|
||||
Component/ComponentApplicationLifecycle.h
|
||||
Component/ComponentBus.cpp
|
||||
Component/ComponentBus.h
|
||||
Component/ComponentExport.h
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/Math/Crc.h>
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/Component/ComponentApplicationLifecycle.h>
|
||||
#include <AzCore/Component/NonUniformScaleBus.h>
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/Memory/MemoryComponent.h>
|
||||
@@ -120,6 +121,11 @@ namespace AzFramework
|
||||
m_archiveFileIO = AZStd::make_unique<AZ::IO::ArchiveFileIO>(m_archive.get());
|
||||
AZ::IO::FileIOBase::SetInstance(m_archiveFileIO.get());
|
||||
SetFileIOAliases();
|
||||
// The FileIOAvailable event needs to be registered here as this event is sent out
|
||||
// before the settings registry has merged the .setreg files from the <engine-root>
|
||||
// (That happens in MergeSettingsToRegistry
|
||||
AZ::ComponentApplicationLifecycle::RegisterEvent(*m_settingsRegistry, "FileIOAvailable");
|
||||
AZ::ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "FileIOAvailable", R"({})");
|
||||
}
|
||||
|
||||
if (auto nativeUI = AZ::Interface<AZ::NativeUI::NativeUIRequests>::Get(); nativeUI == nullptr)
|
||||
@@ -172,6 +178,8 @@ namespace AzFramework
|
||||
// Archive classes relies on the FileIOBase DirectInstance to close
|
||||
// files properly
|
||||
m_directFileIO.reset();
|
||||
|
||||
AZ::ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "FileIOUnavailable", R"({})");
|
||||
}
|
||||
|
||||
void Application::Start(const Descriptor& descriptor, const StartupParameters& startupParameters)
|
||||
@@ -196,7 +204,25 @@ namespace AzFramework
|
||||
systemEntity->Activate();
|
||||
AZ_Assert(systemEntity->GetState() == AZ::Entity::State::Active, "System Entity failed to activate.");
|
||||
|
||||
m_isStarted = (systemEntity->GetState() == AZ::Entity::State::Active);
|
||||
|
||||
if (m_isStarted = (systemEntity->GetState() == AZ::Entity::State::Active); m_isStarted)
|
||||
{
|
||||
if (m_startupParameters.m_loadAssetCatalog)
|
||||
{
|
||||
// Start Monitoring Asset changes over the network and load the AssetCatalog
|
||||
auto StartMonitoringAssetsAndLoadCatalog = [this](AZ::Data::AssetCatalogRequests* assetCatalogRequests)
|
||||
{
|
||||
if (AZ::IO::FixedMaxPath assetCatalogPath;
|
||||
m_settingsRegistry->Get(assetCatalogPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder))
|
||||
{
|
||||
assetCatalogPath /= "assetcatalog.xml";
|
||||
assetCatalogRequests->LoadCatalog(assetCatalogPath.c_str());
|
||||
}
|
||||
};
|
||||
using AssetCatalogBus = AZ::Data::AssetCatalogRequestBus;
|
||||
AssetCatalogBus::Broadcast(AZStd::move(StartMonitoringAssetsAndLoadCatalog));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::PreModuleLoad()
|
||||
@@ -210,6 +236,17 @@ namespace AzFramework
|
||||
{
|
||||
if (m_isStarted)
|
||||
{
|
||||
if (m_startupParameters.m_loadAssetCatalog)
|
||||
{
|
||||
// Stop Monitoring Assets changes
|
||||
auto StopMonitoringAssets = [](AZ::Data::AssetCatalogRequests* assetCatalogRequests)
|
||||
{
|
||||
assetCatalogRequests->StopMonitoringAssets();
|
||||
};
|
||||
using AssetCatalogBus = AZ::Data::AssetCatalogRequestBus;
|
||||
AssetCatalogBus::Broadcast(AZStd::move(StopMonitoringAssets));
|
||||
}
|
||||
|
||||
ApplicationLifecycleEvents::Bus::Broadcast(&ApplicationLifecycleEvents::OnApplicationAboutToStop);
|
||||
|
||||
m_pimpl.reset();
|
||||
|
||||
@@ -565,7 +565,7 @@ namespace AzFramework
|
||||
|
||||
if (!bytes.empty())
|
||||
{
|
||||
AZStd::shared_ptr < AzFramework::AssetRegistry> prevRegistry;
|
||||
AZStd::shared_ptr<AzFramework::AssetRegistry> prevRegistry;
|
||||
if (!m_initialized)
|
||||
{
|
||||
// First time initialization may have updates already processed which we want to apply
|
||||
@@ -589,7 +589,6 @@ namespace AzFramework
|
||||
AZ_TracePrintf("AssetCatalog", "Loaded registry containing %u assets.\n", m_registry->m_assetIdToInfo.size());
|
||||
|
||||
// It's currently possible in tools for us to have received updates from AP which were applied before the catalog was ready to load
|
||||
// due to CryPak and CrySystem coming online later than our components
|
||||
if (!m_initialized)
|
||||
{
|
||||
ApplyDeltaCatalog(prevRegistry);
|
||||
@@ -611,12 +610,13 @@ namespace AzFramework
|
||||
// the mutex. If the listener tries to perform a blocking asset load via GetAsset() / BlockUntilLoadComplete(), the spawned asset
|
||||
// thread will make a call to the AssetCatalogRequestBus and block on the held mutex. This would cause a deadlock, since the listener
|
||||
// won't free the mutex until the load is complete.
|
||||
// So instead, queue the notification until the next tick, so that it doesn't occur within the AssetCatalogRequestBus mutex, and also
|
||||
// So instead, queue the notification until after the AssetCatalogRequestBus mutex is unlocked for the current thread, and also
|
||||
// so that the entire AssetCatalog initialization is complete.
|
||||
AZ::TickBus::QueueFunction([catalogRegistryString = AZStd::string(catalogRegistryFile)]()
|
||||
{
|
||||
AssetCatalogEventBus::Broadcast(&AssetCatalogEventBus::Events::OnCatalogLoaded, catalogRegistryString.c_str());
|
||||
});
|
||||
auto OnCatalogLoaded = [catalogRegistryString = AZStd::string(catalogRegistryFile)]()
|
||||
{
|
||||
AssetCatalogEventBus::Broadcast(&AssetCatalogEventBus::Events::OnCatalogLoaded, catalogRegistryString.c_str());
|
||||
};
|
||||
AZ::Data::AssetCatalogRequestBus::QueueFunction(AZStd::move(OnCatalogLoaded));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -978,6 +978,7 @@ namespace AzFramework
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_registryMutex);
|
||||
|
||||
m_registry->Clear();
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace AzFramework
|
||||
//=========================================================================
|
||||
void AssetRegistry::Clear()
|
||||
{
|
||||
m_assetDependencies = {};
|
||||
m_assetIdToInfo = AssetIdToInfoMap();
|
||||
m_assetPathToId = AssetPathToIdMap();
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzCore/std/string/wildcard.h>
|
||||
#include <AzCore/std/string/regex.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzCore/XML/rapidxml.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/Asset/FileTagAsset.h>
|
||||
@@ -89,19 +89,19 @@ namespace AzFramework
|
||||
bool FileTagManager::Save(FileTagType fileTagType, const AZStd::string& destinationFilePath = AZStd::string())
|
||||
{
|
||||
AzFramework::FileTag::FileTagAsset* fileTagAsset = GetFileTagAsset(fileTagType);
|
||||
AZStd::string filePathToSave = destinationFilePath;
|
||||
AZ::IO::Path filePathToSave = destinationFilePath;
|
||||
if (filePathToSave.empty())
|
||||
{
|
||||
filePathToSave = FileTagQueryManager::GetDefaultFileTagFilePath(fileTagType);
|
||||
}
|
||||
|
||||
if (!AzFramework::StringFunc::EndsWith(filePathToSave, AzFramework::FileTag::FileTagAsset::Extension()))
|
||||
if (!filePathToSave.Extension().Native().ends_with(AzFramework::FileTag::FileTagAsset::Extension()))
|
||||
{
|
||||
AZ_Error("FileTag", false, "Unable to save tag file (%s). Invalid file extension, file tag can only have (%s) extension.\n", filePathToSave.c_str(), AzFramework::FileTag::FileTagAsset::Extension());
|
||||
return false;
|
||||
}
|
||||
|
||||
return AZ::Utils::SaveObjectToFile(filePathToSave, AZ::DataStream::StreamType::ST_XML, fileTagAsset);
|
||||
return AZ::Utils::SaveObjectToFile(filePathToSave.Native(), AZ::DataStream::StreamType::ST_XML, fileTagAsset);
|
||||
}
|
||||
|
||||
AZ::Outcome<AZStd::string, AZStd::string> FileTagManager::AddTagsInternal(AZStd::string filePath, FileTagType fileTagType, AZStd::vector<AZStd::string> fileTags, AzFramework::FileTag::FilePatternType filePatternType)
|
||||
@@ -239,17 +239,22 @@ namespace AzFramework
|
||||
QueryFileTagsEventBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
AZStd::string FileTagQueryManager::GetDefaultFileTagFilePath(FileTagType fileTagType)
|
||||
AZ::IO::Path FileTagQueryManager::GetDefaultFileTagFilePath(FileTagType fileTagType)
|
||||
{
|
||||
auto destinationFilePath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / EngineAssetSourceRelPath;
|
||||
AZ::IO::Path destinationFilePath;
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
settingsRegistry->Get(destinationFilePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
|
||||
}
|
||||
destinationFilePath /= EngineAssetSourceRelPath;
|
||||
destinationFilePath /= fileTagType == FileTagType::Exclude ? ExcludeFileName : IncludeFileName;
|
||||
destinationFilePath.ReplaceExtension(AzFramework::FileTag::FileTagAsset::Extension());
|
||||
return destinationFilePath.String();
|
||||
return destinationFilePath;
|
||||
}
|
||||
|
||||
bool FileTagQueryManager::Load(const AZStd::string& filePath)
|
||||
{
|
||||
AZStd::string fileToLoad = filePath;
|
||||
AZ::IO::Path fileToLoad = filePath;
|
||||
if (fileToLoad.empty())
|
||||
{
|
||||
fileToLoad = GetDefaultFileTagFilePath(m_fileTagType);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/std/containers/map.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/IO/Path/Path_fwd.h>
|
||||
#include <AzFramework/FileTag/FileTagBus.h>
|
||||
|
||||
namespace AzFramework
|
||||
@@ -88,7 +89,7 @@ namespace AzFramework
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static AZStd::string GetDefaultFileTagFilePath(FileTagType fileTagType);
|
||||
static AZ::IO::Path GetDefaultFileTagFilePath(FileTagType fileTagType);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <AzCore/std/string/wildcard.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/XML/rapidxml.h>
|
||||
|
||||
namespace AzFramework
|
||||
@@ -66,7 +67,8 @@ namespace AzFramework
|
||||
m_excludeFileQueryManager.reset(aznew FileTagQueryManager(FileTagType::Exclude));
|
||||
if (!m_excludeFileQueryManager.get()->Load())
|
||||
{
|
||||
AZ_Error("FileTagQueryComponent", false, "Not able to load default exclude file (%s). Please make sure that it exists on disk.\n", FileTagQueryManager::GetDefaultFileTagFilePath(FileTagType::Exclude).c_str());
|
||||
AZ_Error("FileTagQueryComponent", false, "Not able to load default exclude file (%s). Please make sure that it exists on disk.\n",
|
||||
FileTagQueryManager::GetDefaultFileTagFilePath(FileTagType::Exclude).c_str());
|
||||
}
|
||||
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
|
||||
|
||||
@@ -308,7 +308,9 @@ namespace UnitTest
|
||||
registry->Set(projectPathKey, "AutomatedTesting");
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry);
|
||||
|
||||
m_app->Start(desc);
|
||||
AZ::ComponentApplication::StartupParameters startupParameters;
|
||||
startupParameters.m_loadAssetCatalog = false;
|
||||
m_app->Start(desc, startupParameters);
|
||||
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
|
||||
+33
-17
@@ -943,13 +943,15 @@ namespace AzToolsFramework
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const int count = rowCount(parent);
|
||||
AZ::EntityId newParentId = GetEntityFromIndex(parent);
|
||||
AZ::EntityId beforeEntityId = GetEntityFromIndex(index(row, 0, parent));
|
||||
AZ::EntityId beforeEntityId = (row >= 0 && row < count) ? GetEntityFromIndex(index(row, 0, parent)) : AZ::EntityId();
|
||||
EntityIdList topLevelEntityIds;
|
||||
topLevelEntityIds.reserve(entityIdListContainer.m_entityIds.size());
|
||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::FindTopLevelEntityIdsInactive, entityIdListContainer.m_entityIds, topLevelEntityIds);
|
||||
if (!ReparentEntities(newParentId, topLevelEntityIds, beforeEntityId))
|
||||
const auto appendActionForInvalid = newParentId.IsValid() && (row >= count) ? AppendEnd : AppendBeginning;
|
||||
if (!ReparentEntities(newParentId, topLevelEntityIds, beforeEntityId, appendActionForInvalid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1046,7 +1048,7 @@ namespace AzToolsFramework
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EntityOutlinerListModel::ReparentEntities(const AZ::EntityId& newParentId, const EntityIdList &selectedEntityIds, const AZ::EntityId& beforeEntityId)
|
||||
bool EntityOutlinerListModel::ReparentEntities(const AZ::EntityId& newParentId, const EntityIdList &selectedEntityIds, const AZ::EntityId& beforeEntityId, ReparentForInvalid forInvalid)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
if (!CanReparentEntities(newParentId, selectedEntityIds))
|
||||
@@ -1056,10 +1058,18 @@ namespace AzToolsFramework
|
||||
|
||||
m_isFilterDirty = true;
|
||||
|
||||
ScopedUndoBatch undo("Reparent Entities");
|
||||
//capture child entity order before re-parent operation, which will automatically add order info if not present
|
||||
EntityOrderArray entityOrderArray = GetEntityChildOrder(newParentId);
|
||||
|
||||
//search for the insertion entity in the order array
|
||||
const auto beforeEntityItr = AZStd::find(entityOrderArray.begin(), entityOrderArray.end(), beforeEntityId);
|
||||
const bool hasInvalidIndex = beforeEntityItr == entityOrderArray.end();
|
||||
if (hasInvalidIndex && forInvalid == None)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedUndoBatch undo("Reparent Entities");
|
||||
// The new parent is dirty due to sort change(s)
|
||||
undo.MarkEntityDirty(GetEntityIdForSortInfo(newParentId));
|
||||
|
||||
@@ -1088,9 +1098,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
//search for the insertion entity in the order array
|
||||
auto beforeEntityItr = AZStd::find(entityOrderArray.begin(), entityOrderArray.end(), beforeEntityId);
|
||||
|
||||
|
||||
//replace order info matching selection with bad values rather than remove to preserve layout
|
||||
for (auto& id : entityOrderArray)
|
||||
{
|
||||
@@ -1100,17 +1108,25 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
if (newParentId.IsValid())
|
||||
//if adding to a valid parent entity, insert at the found entity location or at the head/tail depending on placeAtTail flag
|
||||
if (hasInvalidIndex)
|
||||
{
|
||||
//if adding to a valid parent entity, insert at the found entity location or at the head of the container
|
||||
auto insertItr = beforeEntityItr != entityOrderArray.end() ? beforeEntityItr : entityOrderArray.begin();
|
||||
entityOrderArray.insert(insertItr, processedEntityIds.begin(), processedEntityIds.end());
|
||||
}
|
||||
else
|
||||
switch(forInvalid)
|
||||
{
|
||||
case AppendEnd:
|
||||
entityOrderArray.insert(entityOrderArray.end(), processedEntityIds.begin(), processedEntityIds.end());
|
||||
break;
|
||||
case AppendBeginning:
|
||||
entityOrderArray.insert(entityOrderArray.begin(), processedEntityIds.begin(), processedEntityIds.end());
|
||||
break;
|
||||
default:
|
||||
AZ_Assert(false, "Unexpected type for ReparentForInvalid");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//if adding to an invalid parent entity (the root), insert at the found entity location or at the tail of the container
|
||||
auto insertItr = beforeEntityItr != entityOrderArray.end() ? beforeEntityItr : entityOrderArray.end();
|
||||
entityOrderArray.insert(insertItr, processedEntityIds.begin(), processedEntityIds.end());
|
||||
entityOrderArray.insert(beforeEntityItr, processedEntityIds.begin(), processedEntityIds.end());
|
||||
}
|
||||
|
||||
//remove placeholder entity ids
|
||||
|
||||
+8
-1
@@ -72,6 +72,13 @@ namespace AzToolsFramework
|
||||
ColumnCount //!< Total number of columns
|
||||
};
|
||||
|
||||
enum ReparentForInvalid
|
||||
{
|
||||
None, //!< For an invalid location the entity does not change location
|
||||
AppendEnd, //!< Append Item to end of target parent list
|
||||
AppendBeginning, //!< Append Item to the beginning of target parent list
|
||||
};
|
||||
|
||||
// Note: the ColumnSortIndex column isn't shown, hence the -1 and the need for a separate counter.
|
||||
// A wrong column count number causes refresh issues and hover mismatch on model update.
|
||||
static const int VisibleColumnCount = ColumnCount - 1;
|
||||
@@ -162,7 +169,7 @@ namespace AzToolsFramework
|
||||
|
||||
// Buffer Processing Slots - These are called using single-shot events when the buffers begin to fill.
|
||||
bool CanReparentEntities(const AZ::EntityId& newParentId, const EntityIdList& selectedEntityIds) const;
|
||||
bool ReparentEntities(const AZ::EntityId& newParentId, const EntityIdList& selectedEntityIds, const AZ::EntityId& beforeEntityId = AZ::EntityId());
|
||||
bool ReparentEntities(const AZ::EntityId& newParentId, const EntityIdList& selectedEntityIds, const AZ::EntityId& beforeEntityId = AZ::EntityId(), ReparentForInvalid forInvalid = None);
|
||||
|
||||
//! Use the current filter setting and re-evaluate the filter.
|
||||
void InvalidateFilter();
|
||||
|
||||
@@ -242,7 +242,7 @@ void IDebugCallStack::WriteLineToLog(const char* format, ...)
|
||||
va_end(ArgList);
|
||||
|
||||
AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Open("@Log@\\error.log", AZ::IO::GetOpenModeFromStringMode("a+t"), fileHandle);
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Open("@log@\\error.log", AZ::IO::GetOpenModeFromStringMode("a+t"), fileHandle);
|
||||
if (fileHandle != AZ::IO::InvalidHandle)
|
||||
{
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Write(fileHandle, szBuffer, strlen(szBuffer));
|
||||
@@ -254,7 +254,7 @@ void IDebugCallStack::WriteLineToLog(const char* format, ...)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void IDebugCallStack::StartMemLog()
|
||||
{
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Open("@Log@\\memallocfile.log", AZ::IO::OpenMode::ModeWrite, m_memAllocFileHandle);
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Open("@log@\\memallocfile.log", AZ::IO::OpenMode::ModeWrite, m_memAllocFileHandle);
|
||||
|
||||
assert(m_memAllocFileHandle != AZ::IO::InvalidHandle);
|
||||
}
|
||||
|
||||
@@ -61,8 +61,12 @@ namespace AssetBundler
|
||||
{
|
||||
AZStd::string absolutePath = filePath.toUtf8().data();
|
||||
if (AZ::IO::FileIOBase::GetInstance()->Exists(absolutePath.c_str()))
|
||||
{
|
||||
AZStd::string projectName = pathToProjectNameMap.at(absolutePath);
|
||||
{
|
||||
AZStd::string projectName;
|
||||
if (pathToProjectNameMap.contains(absolutePath))
|
||||
{
|
||||
projectName = pathToProjectNameMap.at(absolutePath);
|
||||
}
|
||||
|
||||
// If a project name is already specified, then the associated file is a default file
|
||||
LoadFile(absolutePath, projectName, !projectName.empty());
|
||||
|
||||
@@ -3576,23 +3576,24 @@ namespace AssetProcessor
|
||||
// Absolute path, just check the 1 scan folder
|
||||
if (AZ::IO::PathView(encodedFileData.toUtf8().constData()).IsAbsolute())
|
||||
{
|
||||
QString scanFolderName;
|
||||
if (!m_platformConfig->ConvertToRelativePath(encodedFileData, resultDatabaseSourceName, scanFolderName))
|
||||
auto scanFolderInfo = m_platformConfig->GetScanFolderForFile(encodedFileData);
|
||||
|
||||
if (!m_platformConfig->ConvertToRelativePath(encodedFileData, scanFolderInfo, resultDatabaseSourceName))
|
||||
{
|
||||
AZ_Warning(
|
||||
AssetProcessor::ConsoleChannel, false,
|
||||
"'%s' does not appear to be in any input folder. Use relative paths instead.",
|
||||
sourceDependency.m_sourceFileDependencyPath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make an absolute path that is ScanFolderPath + Part of search path before the wildcard
|
||||
QDir rooted(scanFolderInfo->ScanPath());
|
||||
QString scanFolderAndKnownSubPath = rooted.absoluteFilePath(knownPathBeforeWildcard);
|
||||
|
||||
auto scanFolderInfo = m_platformConfig->GetScanFolderByPath(scanFolderName);
|
||||
|
||||
// Make an absolute path that is ScanFolderPath + Part of search path before the wildcard
|
||||
QDir rooted(scanFolderName);
|
||||
QString scanFolderAndKnownSubPath = rooted.absoluteFilePath(knownPathBeforeWildcard);
|
||||
|
||||
resolvedDependencyList.append(m_platformConfig->FindWildcardMatches(
|
||||
scanFolderAndKnownSubPath, relativeSearch, false, scanFolderInfo->RecurseSubFolders()));
|
||||
resolvedDependencyList.append(m_platformConfig->FindWildcardMatches(
|
||||
scanFolderAndKnownSubPath, relativeSearch, false, scanFolderInfo->RecurseSubFolders()));
|
||||
}
|
||||
}
|
||||
else // Relative path, check every scan folder
|
||||
{
|
||||
|
||||
@@ -88,6 +88,7 @@ public:
|
||||
friend struct DuplicateProductsTest;
|
||||
friend struct DuplicateProcessTest;
|
||||
friend struct AbsolutePathProductDependencyTest;
|
||||
friend struct WildcardSourceDependencyTest;
|
||||
|
||||
explicit AssetProcessorManager_Test(PlatformConfiguration* config, QObject* parent = nullptr);
|
||||
~AssetProcessorManager_Test() override;
|
||||
@@ -5308,3 +5309,141 @@ TEST_F(MetadataFileTest, MetadataFile_SourceFileExtensionDifferentCase)
|
||||
ASSERT_TRUE(BlockUntilIdle(5000));
|
||||
ASSERT_EQ(jobDetails.m_jobEntry.m_pathRelativeToWatchFolder, relFileName);
|
||||
}
|
||||
|
||||
bool WildcardSourceDependencyTest::Test(
|
||||
const AZStd::string& dependencyPath, AZStd::vector<AZStd::string>& resolvedPaths)
|
||||
{
|
||||
[[maybe_unused]] QString resolvedName;
|
||||
QStringList stringlistPaths;
|
||||
AssetBuilderSDK::SourceFileDependency dependency(dependencyPath, AZ::Uuid::CreateNull(), AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards);
|
||||
bool result = m_assetProcessorManager->ResolveSourceFileDependencyPath(dependency, resolvedName, stringlistPaths);
|
||||
|
||||
// Convert to a vector of AZStd::strings because GTest handles this type better when displaying errors
|
||||
for (const QString& resolvedPath : stringlistPaths)
|
||||
{
|
||||
resolvedPaths.emplace_back(resolvedPath.toUtf8().constData());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void WildcardSourceDependencyTest::SetUp()
|
||||
{
|
||||
AssetProcessorManagerTest::SetUp();
|
||||
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
// Add a non-recursive scan folder. Only files directly inside of this folder should be picked up, subfolders are ignored
|
||||
m_config->AddScanFolder(ScanFolderInfo(tempPath.filePath("no_recurse"), "no_recurse",
|
||||
"no_recurse", false, false, m_config->GetEnabledPlatforms(), 1));
|
||||
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder1/1a.foo"));
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder1/1b.foo"));
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder2/redirected/a.foo"));
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder2/redirected/b.foo"));
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder2/redirected/folder/one/c.foo"));
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder2/redirected/folder/one/d.foo"));
|
||||
|
||||
// Add a file that is not in a scanfolder. Should always be ignored
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("not/a/scanfolder/e.foo"));
|
||||
|
||||
// Add a file in the non-recursive scanfolder. Since its not directly in the scan folder, it should always be ignored
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("no_recurse/one/two/three/f.foo"));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_Broad)
|
||||
{
|
||||
// Expect all files except for the 2 invalid ones (e and f)
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
|
||||
ASSERT_TRUE(Test("*.foo", resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre("a.foo", "b.foo", "folder/one/c.foo", "folder/one/d.foo", "1a.foo", "1b.foo"));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_WithFolder)
|
||||
{
|
||||
// Make sure we can filter to files under a folder
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
|
||||
ASSERT_TRUE(Test("folder/*.foo", resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre("folder/one/c.foo", "folder/one/d.foo"));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_WildcardPath)
|
||||
{
|
||||
// Make sure the * wildcard works even if the full filename is given
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
|
||||
ASSERT_TRUE(Test("*a.foo", resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre("a.foo", "1a.foo"));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Absolute_WithFolder)
|
||||
{
|
||||
// Make sure we can use absolute paths to filter to files under a folder
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_TRUE(Test(tempPath.absoluteFilePath("subfolder2/redirected/*.foo").toUtf8().constData(), resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre("a.foo", "b.foo", "folder/one/c.foo", "folder/one/d.foo"));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Absolute_NotInScanfolder)
|
||||
{
|
||||
// Files outside a scanfolder should not be returned even with an absolute path
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_TRUE(Test(tempPath.absoluteFilePath("not/a/scanfolder/*.foo").toUtf8().constData(), resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_NotInScanfolder)
|
||||
{
|
||||
// Files outside a scanfolder should not be returned
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_TRUE(Test("*/e.foo", resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_InNonRecursiveScanfolder)
|
||||
{
|
||||
// Files deep inside non-recursive scanfolders should not be returned
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_TRUE(Test("*/f.foo", resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Absolute_InNonRecursiveScanfolder)
|
||||
{
|
||||
// Absolute paths to files deep inside non-recursive scanfolders should not be returned
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_TRUE(Test(tempPath.absoluteFilePath("one/two/three/*.foo").toUtf8().constData(), resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_NoWildcard)
|
||||
{
|
||||
// No wildcard results in a failure
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_FALSE(Test("subfolder1/1a.foo", resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Absolute_NoWildcard)
|
||||
{
|
||||
// No wildcard results in a failure
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_FALSE(Test(tempPath.absoluteFilePath("subfolder1/1a.foo").toUtf8().constData(), resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
@@ -131,6 +131,14 @@ struct MultiplatformPathDependencyTest
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
struct WildcardSourceDependencyTest
|
||||
: AssetProcessorManagerTest
|
||||
{
|
||||
bool Test(const AZStd::string& dependencyPath, AZStd::vector<AZStd::string>& resolvedPaths);
|
||||
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
struct MockBuilderInfoHandler
|
||||
: public AssetProcessor::AssetBuilderInfoBus::Handler
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@ ly_add_target(
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
Platform/${PAL_PLATFORM_NAME}
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
|
||||
@@ -11,4 +11,6 @@ set(FILES
|
||||
ProjectBuilderWorker_linux.cpp
|
||||
ProjectUtils_linux.cpp
|
||||
ProjectManagerDefs_linux.cpp
|
||||
ProjectManager_Traits_Platform.h
|
||||
ProjectManager_Traits_Linux.h
|
||||
)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR false
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ProjectManager_Traits_Linux.h>
|
||||
@@ -11,4 +11,6 @@ set(FILES
|
||||
ProjectBuilderWorker_mac.cpp
|
||||
ProjectUtils_mac.cpp
|
||||
ProjectManagerDefs_mac.cpp
|
||||
ProjectManager_Traits_Platform.h
|
||||
ProjectManager_Traits_Mac.h
|
||||
)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR false
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ProjectManager_Traits_Mac.h>
|
||||
@@ -11,4 +11,6 @@ set(FILES
|
||||
ProjectBuilderWorker_windows.cpp
|
||||
ProjectUtils_windows.cpp
|
||||
ProjectManagerDefs_windows.cpp
|
||||
ProjectManager_Traits_Platform.h
|
||||
ProjectManager_Traits_Windows.h
|
||||
)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ProjectManager_Traits_Windows.h>
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR true
|
||||
@@ -9,7 +9,7 @@ QMainWindow {
|
||||
|
||||
#ScreensCtrl {
|
||||
min-width:1200px;
|
||||
min-height:800px;
|
||||
min-height:700px;
|
||||
}
|
||||
|
||||
QPushButton:focus {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <AzQtComponents/Utilities/HandleDpiAwareness.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
|
||||
#include <ProjectManager_Traits_Platform.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
@@ -194,8 +195,12 @@ namespace O3DE::ProjectManager
|
||||
// set stylesheet after creating the main window or their styles won't get updated
|
||||
AzQtComponents::StyleManager::setStyleSheet(m_mainWindow.data(), QStringLiteral("style:ProjectManager.qss"));
|
||||
|
||||
// the decoration wrapper is intended to remember window positioning and sizing
|
||||
// the decoration wrapper is intended to remember window positioning and sizing
|
||||
#if AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR
|
||||
auto wrapper = new AzQtComponents::WindowDecorationWrapper();
|
||||
#else
|
||||
auto wrapper = new AzQtComponents::WindowDecorationWrapper(AzQtComponents::WindowDecorationWrapper::OptionDisabled);
|
||||
#endif
|
||||
wrapper->setGuest(m_mainWindow.data());
|
||||
|
||||
// show the main window here to apply the stylesheet before restoring geometry or we
|
||||
|
||||
@@ -81,8 +81,6 @@ namespace AZ
|
||||
|
||||
// Load the asset catalog so that we can find any nested assets successfully. We also need to tick the tick bus
|
||||
// so that the OnCatalogLoaded event gets processed now, instead of during application shutdown.
|
||||
AZ::Data::AssetCatalogRequestBus::Broadcast(
|
||||
&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@products@/assetcatalog.xml");
|
||||
application.Tick();
|
||||
|
||||
AZStd::string logggingScratchBuffer;
|
||||
|
||||
@@ -175,8 +175,6 @@ namespace AtomToolsFramework
|
||||
AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast(
|
||||
&AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized);
|
||||
|
||||
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@products@/assetcatalog.xml");
|
||||
|
||||
if (!AZ::RPI::RPISystemInterface::Get()->IsInitialized())
|
||||
{
|
||||
AZ::RPI::RPISystemInterface::Get()->InitializeSystemAssets();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/EMotionFXAtom">
|
||||
<file>Camera_category.svg</file>
|
||||
<file>Visualization.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 60 (88103) - https://sketch.com -->
|
||||
<title>Icons / System / View</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="Icons-/-System-/-View" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 977 B |
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AtomActorDebugDraw.h>
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
#include <Atom/RPI.Public/AuxGeom/AuxGeomDraw.h>
|
||||
#include <Atom/RPI.Public/AuxGeom/AuxGeomFeatureProcessorInterface.h>
|
||||
#include <Integration/Rendering/RenderActorInstance.h>
|
||||
|
||||
#include <EMotionFX/Source/ActorInstance.h>
|
||||
#include <EMotionFX/Source/DebugDraw.h>
|
||||
#include <EMotionFX/Source/EMotionFXManager.h>
|
||||
#include <EMotionFX/Source/SubMesh.h>
|
||||
#include <EMotionFX/Source/TransformData.h>
|
||||
#include <EMotionFX/Source/Mesh.h>
|
||||
#include <EMotionFX/Source/Node.h>
|
||||
|
||||
namespace AZ::Render
|
||||
{
|
||||
AtomActorDebugDraw::AtomActorDebugDraw(AZ::EntityId entityId)
|
||||
{
|
||||
m_auxGeomFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity<RPI::AuxGeomFeatureProcessorInterface>(entityId);
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::DebugDraw(const EMotionFX::ActorRenderFlagBitset& renderFlags, EMotionFX::ActorInstance* instance)
|
||||
{
|
||||
if (!m_auxGeomFeatureProcessor || !instance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue();
|
||||
if (!auxGeom)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Render aabb
|
||||
if (renderFlags[EMotionFX::ActorRenderFlag::RENDER_AABB])
|
||||
{
|
||||
RenderAABB(instance);
|
||||
}
|
||||
|
||||
// Render skeleton
|
||||
if (renderFlags[EMotionFX::ActorRenderFlag::RENDER_LINESKELETON])
|
||||
{
|
||||
RenderSkeleton(instance);
|
||||
}
|
||||
|
||||
// Render internal EMFX debug lines.
|
||||
if (renderFlags[EMotionFX::ActorRenderFlag::RENDER_EMFX_DEBUG])
|
||||
{
|
||||
RenderEMFXDebugDraw(instance);
|
||||
}
|
||||
|
||||
// Render vertex normal, face normal, tagent and wireframe.
|
||||
const bool renderVertexNormals = renderFlags[EMotionFX::ActorRenderFlag::RENDER_VERTEXNORMALS];
|
||||
const bool renderFaceNormals = renderFlags[EMotionFX::ActorRenderFlag::RENDER_FACENORMALS];
|
||||
const bool renderTangents = renderFlags[EMotionFX::ActorRenderFlag::RENDER_TANGENTS];
|
||||
const bool renderWireframe = renderFlags[EMotionFX::ActorRenderFlag::RENDER_WIREFRAME];
|
||||
|
||||
if (renderVertexNormals || renderFaceNormals || renderTangents || renderWireframe)
|
||||
{
|
||||
// Iterate through all enabled nodes
|
||||
const EMotionFX::Pose* pose = instance->GetTransformData()->GetCurrentPose();
|
||||
const size_t geomLODLevel = instance->GetLODLevel();
|
||||
const size_t numEnabled = instance->GetNumEnabledNodes();
|
||||
for (size_t i = 0; i < numEnabled; ++i)
|
||||
{
|
||||
EMotionFX::Node* node = instance->GetActor()->GetSkeleton()->GetNode(instance->GetEnabledNode(i));
|
||||
EMotionFX::Mesh* mesh = instance->GetActor()->GetMesh(geomLODLevel, node->GetNodeIndex());
|
||||
const AZ::Transform globalTM = pose->GetWorldSpaceTransform(node->GetNodeIndex()).ToAZTransform();
|
||||
|
||||
m_currentMesh = nullptr;
|
||||
|
||||
if (!mesh)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RenderNormals(mesh, globalTM, renderVertexNormals, renderFaceNormals);
|
||||
if (renderTangents)
|
||||
{
|
||||
RenderTangents(mesh, globalTM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::PrepareForMesh(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM)
|
||||
{
|
||||
// Check if we have already prepared for the given mesh
|
||||
if (m_currentMesh == mesh)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Set our new current mesh
|
||||
m_currentMesh = mesh;
|
||||
|
||||
// Get the number of vertices and the data
|
||||
const uint32 numVertices = m_currentMesh->GetNumVertices();
|
||||
AZ::Vector3* positions = (AZ::Vector3*)m_currentMesh->FindVertexData(EMotionFX::Mesh::ATTRIB_POSITIONS);
|
||||
|
||||
// Check if the vertices fits in our buffer
|
||||
if (m_worldSpacePositions.size() < numVertices)
|
||||
{
|
||||
m_worldSpacePositions.resize(numVertices);
|
||||
}
|
||||
|
||||
// Pre-calculate the world space positions
|
||||
for (uint32 i = 0; i < numVertices; ++i)
|
||||
{
|
||||
m_worldSpacePositions[i] = worldTM.TransformPoint(positions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::RenderAABB(EMotionFX::ActorInstance* instance)
|
||||
{
|
||||
RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue();
|
||||
const AZ::Aabb& aabb = instance->GetAabb();
|
||||
auxGeom->DrawAabb(aabb, AZ::Color(0.0f, 1.0f, 1.0f, 1.0f), RPI::AuxGeomDraw::DrawStyle::Line);
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::RenderSkeleton(EMotionFX::ActorInstance* instance)
|
||||
{
|
||||
RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue();
|
||||
|
||||
const EMotionFX::TransformData* transformData = instance->GetTransformData();
|
||||
const EMotionFX::Skeleton* skeleton = instance->GetActor()->GetSkeleton();
|
||||
const EMotionFX::Pose* pose = transformData->GetCurrentPose();
|
||||
|
||||
const size_t lodLevel = instance->GetLODLevel();
|
||||
const size_t numJoints = skeleton->GetNumNodes();
|
||||
|
||||
m_auxVertices.clear();
|
||||
m_auxVertices.reserve(numJoints * 2);
|
||||
|
||||
for (size_t jointIndex = 0; jointIndex < numJoints; ++jointIndex)
|
||||
{
|
||||
const EMotionFX::Node* joint = skeleton->GetNode(jointIndex);
|
||||
if (!joint->GetSkeletalLODStatus(lodLevel))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t parentIndex = joint->GetParentIndex();
|
||||
if (parentIndex == InvalidIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const AZ::Vector3 parentPos = pose->GetWorldSpaceTransform(parentIndex).m_position;
|
||||
m_auxVertices.emplace_back(parentPos);
|
||||
|
||||
const AZ::Vector3 bonePos = pose->GetWorldSpaceTransform(jointIndex).m_position;
|
||||
m_auxVertices.emplace_back(bonePos);
|
||||
}
|
||||
|
||||
const AZ::Color skeletonColor(0.604f, 0.804f, 0.196f, 1.0f);
|
||||
RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs;
|
||||
lineArgs.m_verts = m_auxVertices.data();
|
||||
lineArgs.m_vertCount = static_cast<uint32_t>(m_auxVertices.size());
|
||||
lineArgs.m_colors = &skeletonColor;
|
||||
lineArgs.m_colorCount = 1;
|
||||
lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off;
|
||||
auxGeom->DrawLines(lineArgs);
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::RenderEMFXDebugDraw(EMotionFX::ActorInstance* instance)
|
||||
{
|
||||
RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue();
|
||||
|
||||
EMotionFX::DebugDraw& debugDraw = EMotionFX::GetDebugDraw();
|
||||
debugDraw.Lock();
|
||||
EMotionFX::DebugDraw::ActorInstanceData* actorInstanceData = debugDraw.GetActorInstanceData(instance);
|
||||
actorInstanceData->Lock();
|
||||
const AZStd::vector<EMotionFX::DebugDraw::Line>& lines = actorInstanceData->GetLines();
|
||||
if (lines.empty())
|
||||
{
|
||||
actorInstanceData->Unlock();
|
||||
debugDraw.Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
m_auxVertices.clear();
|
||||
m_auxVertices.reserve(lines.size() * 2);
|
||||
m_auxColors.clear();
|
||||
m_auxColors.reserve(m_auxVertices.size());
|
||||
|
||||
for (const EMotionFX::DebugDraw::Line& line : actorInstanceData->GetLines())
|
||||
{
|
||||
m_auxVertices.emplace_back(line.m_start);
|
||||
m_auxColors.emplace_back(line.m_startColor);
|
||||
m_auxVertices.emplace_back(line.m_end);
|
||||
m_auxColors.emplace_back(line.m_endColor);
|
||||
}
|
||||
|
||||
AZ_Assert(m_auxVertices.size() == m_auxColors.size(), "Number of vertices and number of colors need to match.");
|
||||
actorInstanceData->Unlock();
|
||||
debugDraw.Unlock();
|
||||
|
||||
RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs;
|
||||
lineArgs.m_verts = m_auxVertices.data();
|
||||
lineArgs.m_vertCount = static_cast<uint32_t>(m_auxVertices.size());
|
||||
lineArgs.m_colors = m_auxColors.data();
|
||||
lineArgs.m_colorCount = static_cast<uint32_t>(m_auxColors.size());
|
||||
lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off;
|
||||
auxGeom->DrawLines(lineArgs);
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::RenderNormals(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM, bool vertexNormals, bool faceNormals)
|
||||
{
|
||||
if (!mesh)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vertexNormals && !faceNormals)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue();
|
||||
if (!auxGeom)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Move line color to a render setting.
|
||||
const float faceNormalsScale = 0.01f;
|
||||
const AZ::Color colorFaceNormals = AZ::Colors::Lime;
|
||||
const float vertexNormalsScale = 0.01f;
|
||||
const AZ::Color colorVertexNormals = AZ::Colors::Orange;
|
||||
|
||||
PrepareForMesh(mesh, worldTM);
|
||||
|
||||
AZ::Vector3* normals = (AZ::Vector3*)mesh->FindVertexData(EMotionFX::Mesh::ATTRIB_NORMALS);
|
||||
|
||||
// Render face normals
|
||||
if (faceNormals)
|
||||
{
|
||||
const size_t numSubMeshes = mesh->GetNumSubMeshes();
|
||||
for (uint32 subMeshIndex = 0; subMeshIndex < numSubMeshes; ++subMeshIndex)
|
||||
{
|
||||
EMotionFX::SubMesh* subMesh = mesh->GetSubMesh(subMeshIndex);
|
||||
const uint32 numTriangles = subMesh->GetNumPolygons();
|
||||
const uint32 startVertex = subMesh->GetStartVertex();
|
||||
const uint32* indices = subMesh->GetIndices();
|
||||
|
||||
m_auxVertices.clear();
|
||||
m_auxVertices.reserve(numTriangles * 2);
|
||||
m_auxColors.clear();
|
||||
m_auxColors.reserve(m_auxVertices.size());
|
||||
|
||||
for (uint32 triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex)
|
||||
{
|
||||
const uint32 triangleStartIndex = triangleIndex * 3;
|
||||
const uint32 indexA = indices[triangleStartIndex + 0] + startVertex;
|
||||
const uint32 indexB = indices[triangleStartIndex + 1] + startVertex;
|
||||
const uint32 indexC = indices[triangleStartIndex + 2] + startVertex;
|
||||
|
||||
const AZ::Vector3& posA = m_worldSpacePositions[indexA];
|
||||
const AZ::Vector3& posB = m_worldSpacePositions[indexB];
|
||||
const AZ::Vector3& posC = m_worldSpacePositions[indexC];
|
||||
|
||||
const AZ::Vector3 normalDir = (posB - posA).Cross(posC - posA).GetNormalized();
|
||||
|
||||
// Calculate the center pos
|
||||
const AZ::Vector3 normalPos = (posA + posB + posC) * (1.0f / 3.0f);
|
||||
|
||||
m_auxVertices.emplace_back(normalPos);
|
||||
m_auxColors.emplace_back(colorFaceNormals);
|
||||
m_auxVertices.emplace_back(normalPos + (normalDir * faceNormalsScale));
|
||||
m_auxColors.emplace_back(colorFaceNormals);
|
||||
}
|
||||
}
|
||||
|
||||
RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs;
|
||||
lineArgs.m_verts = m_auxVertices.data();
|
||||
lineArgs.m_vertCount = static_cast<uint32_t>(m_auxVertices.size());
|
||||
lineArgs.m_colors = m_auxColors.data();
|
||||
lineArgs.m_colorCount = static_cast<uint32_t>(m_auxColors.size());
|
||||
lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off;
|
||||
auxGeom->DrawLines(lineArgs);
|
||||
}
|
||||
|
||||
// render vertex normals
|
||||
if (vertexNormals)
|
||||
{
|
||||
const size_t numSubMeshes = mesh->GetNumSubMeshes();
|
||||
for (uint32 subMeshIndex = 0; subMeshIndex < numSubMeshes; ++subMeshIndex)
|
||||
{
|
||||
EMotionFX::SubMesh* subMesh = mesh->GetSubMesh(subMeshIndex);
|
||||
const uint32 numVertices = subMesh->GetNumVertices();
|
||||
const uint32 startVertex = subMesh->GetStartVertex();
|
||||
|
||||
m_auxVertices.clear();
|
||||
m_auxVertices.reserve(numVertices * 2);
|
||||
m_auxColors.clear();
|
||||
m_auxColors.reserve(m_auxVertices.size());
|
||||
|
||||
for (uint32 j = 0; j < numVertices; ++j)
|
||||
{
|
||||
const uint32 vertexIndex = j + startVertex;
|
||||
const AZ::Vector3& position = m_worldSpacePositions[vertexIndex];
|
||||
const AZ::Vector3 normal = worldTM.TransformVector(normals[vertexIndex]).GetNormalizedSafe() * vertexNormalsScale;
|
||||
|
||||
m_auxVertices.emplace_back(position);
|
||||
m_auxColors.emplace_back(colorFaceNormals);
|
||||
m_auxVertices.emplace_back(position + normal);
|
||||
m_auxColors.emplace_back(colorFaceNormals);
|
||||
}
|
||||
}
|
||||
|
||||
RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs;
|
||||
lineArgs.m_verts = m_auxVertices.data();
|
||||
lineArgs.m_vertCount = static_cast<uint32_t>(m_auxVertices.size());
|
||||
lineArgs.m_colors = m_auxColors.data();
|
||||
lineArgs.m_colorCount = static_cast<uint32_t>(m_auxColors.size());
|
||||
lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off;
|
||||
auxGeom->DrawLines(lineArgs);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::RenderTangents(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM)
|
||||
{
|
||||
if (!mesh)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue();
|
||||
if (!auxGeom)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Move line color to a render setting.
|
||||
const AZ::Color colorTangents = AZ::Colors::Red;
|
||||
const AZ::Color mirroredBitangentColor = AZ::Colors::Yellow;
|
||||
const AZ::Color colorBitangents = AZ::Colors::White;
|
||||
const float scale = 0.01f;
|
||||
|
||||
// Get the tangents and check if this mesh actually has tangents
|
||||
AZ::Vector4* tangents = static_cast<AZ::Vector4*>(mesh->FindVertexData(EMotionFX::Mesh::ATTRIB_TANGENTS));
|
||||
if (!tangents)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ::Vector3* bitangents = static_cast<AZ::Vector3*>(mesh->FindVertexData(EMotionFX::Mesh::ATTRIB_BITANGENTS));
|
||||
|
||||
PrepareForMesh(mesh, worldTM);
|
||||
|
||||
AZ::Vector3* normals = (AZ::Vector3*)mesh->FindVertexData(EMotionFX::Mesh::ATTRIB_NORMALS);
|
||||
const uint32 numVertices = mesh->GetNumVertices();
|
||||
|
||||
m_auxVertices.clear();
|
||||
m_auxVertices.reserve(numVertices * 2);
|
||||
m_auxColors.clear();
|
||||
m_auxColors.reserve(m_auxVertices.size());
|
||||
|
||||
// Render the tangents and bitangents
|
||||
AZ::Vector3 orgTangent, tangent, bitangent;
|
||||
for (uint32 i = 0; i < numVertices; ++i)
|
||||
{
|
||||
orgTangent.Set(tangents[i].GetX(), tangents[i].GetY(), tangents[i].GetZ());
|
||||
tangent = (worldTM.TransformVector(orgTangent)).GetNormalized();
|
||||
|
||||
if (bitangents)
|
||||
{
|
||||
bitangent = bitangents[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
bitangent = tangents[i].GetW() * normals[i].Cross(orgTangent);
|
||||
}
|
||||
bitangent = (worldTM.TransformVector(bitangent)).GetNormalizedSafe();
|
||||
|
||||
m_auxVertices.emplace_back(m_worldSpacePositions[i]);
|
||||
m_auxColors.emplace_back(colorTangents);
|
||||
m_auxVertices.emplace_back(m_worldSpacePositions[i] + (tangent * scale));
|
||||
m_auxColors.emplace_back(colorTangents);
|
||||
|
||||
if (tangents[i].GetW() < 0.0f)
|
||||
{
|
||||
m_auxVertices.emplace_back(m_worldSpacePositions[i]);
|
||||
m_auxColors.emplace_back(mirroredBitangentColor);
|
||||
m_auxVertices.emplace_back(m_worldSpacePositions[i] + (bitangent * scale));
|
||||
m_auxColors.emplace_back(mirroredBitangentColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_auxVertices.emplace_back(m_worldSpacePositions[i]);
|
||||
m_auxColors.emplace_back(colorBitangents);
|
||||
m_auxVertices.emplace_back(m_worldSpacePositions[i] + (bitangent * scale));
|
||||
m_auxColors.emplace_back(colorBitangents);
|
||||
}
|
||||
}
|
||||
|
||||
RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs;
|
||||
lineArgs.m_verts = m_auxVertices.data();
|
||||
lineArgs.m_vertCount = static_cast<uint32_t>(m_auxVertices.size());
|
||||
lineArgs.m_colors = m_auxColors.data();
|
||||
lineArgs.m_colorCount = static_cast<uint32_t>(m_auxColors.size());
|
||||
lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off;
|
||||
auxGeom->DrawLines(lineArgs);
|
||||
}
|
||||
} // namespace AZ::Render
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/Math/Color.h>
|
||||
#include <Integration/Rendering/RenderFlag.h>
|
||||
#include <Integration/Rendering/RenderActorInstance.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
class Mesh;
|
||||
class ActorInstance;
|
||||
}
|
||||
|
||||
namespace AZ::RPI
|
||||
{
|
||||
class AuxGeomDraw;
|
||||
class AuxGeomFeatureProcessorInterface;
|
||||
}
|
||||
|
||||
namespace AZ::Render
|
||||
{
|
||||
// Ultility class for atom debug render on actor
|
||||
class AtomActorDebugDraw
|
||||
{
|
||||
public:
|
||||
AtomActorDebugDraw(AZ::EntityId entityId);
|
||||
|
||||
void DebugDraw(const EMotionFX::ActorRenderFlagBitset& renderFlags, EMotionFX::ActorInstance* instance);
|
||||
|
||||
private:
|
||||
|
||||
void PrepareForMesh(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM);
|
||||
void RenderAABB(EMotionFX::ActorInstance* instance);
|
||||
void RenderSkeleton(EMotionFX::ActorInstance* instance);
|
||||
void RenderEMFXDebugDraw(EMotionFX::ActorInstance* instance);
|
||||
void RenderNormals(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM, bool vertexNormals, bool faceNormals);
|
||||
void RenderTangents(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM);
|
||||
|
||||
EMotionFX::Mesh* m_currentMesh = nullptr; /**< A pointer to the mesh whose world space positions are in the pre-calculated positions buffer.
|
||||
NULL in case we haven't pre-calculated any positions yet. */
|
||||
AZStd::vector<AZ::Vector3> m_worldSpacePositions; /**< The buffer used to store world space positions for rendering normals
|
||||
tangents and the wireframe. */
|
||||
|
||||
RPI::AuxGeomFeatureProcessorInterface* m_auxGeomFeatureProcessor = nullptr;
|
||||
AZStd::vector<AZ::Vector3> m_auxVertices;
|
||||
AZStd::vector<AZ::Color> m_auxColors;
|
||||
};
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <AtomActorInstance.h>
|
||||
#include <AtomActor.h>
|
||||
#include <AtomActorDebugDraw.h>
|
||||
#include <ActorAsset.h>
|
||||
|
||||
#include <Atom/Feature/SkinnedMesh/SkinnedMeshInputBuffers.h>
|
||||
@@ -59,7 +60,7 @@ namespace AZ
|
||||
AzFramework::BoundsRequestBus::Handler::BusConnect(m_entityId);
|
||||
}
|
||||
|
||||
m_auxGeomFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity<RPI::AuxGeomFeatureProcessorInterface>(m_entityId);
|
||||
m_atomActorDebugDraw = AZStd::make_unique<AtomActorDebugDraw>(entityId);
|
||||
}
|
||||
|
||||
AtomActorInstance::~AtomActorInstance()
|
||||
@@ -78,6 +79,11 @@ namespace AZ
|
||||
UpdateBounds();
|
||||
}
|
||||
|
||||
void AtomActorInstance::DebugDraw(const EMotionFX::ActorRenderFlagBitset& renderFlags)
|
||||
{
|
||||
m_atomActorDebugDraw->DebugDraw(renderFlags, m_actorInstance);
|
||||
}
|
||||
|
||||
void AtomActorInstance::UpdateBounds()
|
||||
{
|
||||
// Update RenderActorInstance world bounding box
|
||||
@@ -99,116 +105,6 @@ namespace AZ
|
||||
AZ::Interface<AzFramework::IEntityBoundsUnion>::Get()->RefreshEntityLocalBoundsUnion(m_entityId);
|
||||
}
|
||||
|
||||
void AtomActorInstance::DebugDraw(const DebugOptions& debugOptions)
|
||||
{
|
||||
if (m_auxGeomFeatureProcessor)
|
||||
{
|
||||
if (RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue())
|
||||
{
|
||||
if (debugOptions.m_drawAABB)
|
||||
{
|
||||
const AZ::Aabb& aabb = m_actorInstance->GetAabb();
|
||||
auxGeom->DrawAabb(aabb, AZ::Color(0.0f, 1.0f, 1.0f, 1.0f), RPI::AuxGeomDraw::DrawStyle::Line);
|
||||
}
|
||||
|
||||
if (debugOptions.m_drawSkeleton)
|
||||
{
|
||||
RenderSkeleton(auxGeom.get());
|
||||
}
|
||||
|
||||
if (debugOptions.m_emfxDebugDraw)
|
||||
{
|
||||
RenderEMFXDebugDraw(auxGeom.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AtomActorInstance::RenderSkeleton(RPI::AuxGeomDraw* auxGeom)
|
||||
{
|
||||
AZ_Assert(m_actorInstance, "Valid actor instance required.");
|
||||
const EMotionFX::TransformData* transformData = m_actorInstance->GetTransformData();
|
||||
const EMotionFX::Skeleton* skeleton = m_actorInstance->GetActor()->GetSkeleton();
|
||||
const EMotionFX::Pose* pose = transformData->GetCurrentPose();
|
||||
|
||||
const size_t lodLevel = m_actorInstance->GetLODLevel();
|
||||
const size_t numJoints = skeleton->GetNumNodes();
|
||||
|
||||
m_auxVertices.clear();
|
||||
m_auxVertices.reserve(numJoints * 2);
|
||||
|
||||
for (size_t jointIndex = 0; jointIndex < numJoints; ++jointIndex)
|
||||
{
|
||||
const EMotionFX::Node* joint = skeleton->GetNode(jointIndex);
|
||||
if (!joint->GetSkeletalLODStatus(lodLevel))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t parentIndex = joint->GetParentIndex();
|
||||
if (parentIndex == InvalidIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const AZ::Vector3 parentPos = pose->GetWorldSpaceTransform(parentIndex).m_position;
|
||||
m_auxVertices.emplace_back(parentPos);
|
||||
|
||||
const AZ::Vector3 bonePos = pose->GetWorldSpaceTransform(jointIndex).m_position;
|
||||
m_auxVertices.emplace_back(bonePos);
|
||||
}
|
||||
|
||||
const AZ::Color skeletonColor(0.604f, 0.804f, 0.196f, 1.0f);
|
||||
RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs;
|
||||
lineArgs.m_verts = m_auxVertices.data();
|
||||
lineArgs.m_vertCount = static_cast<uint32_t>(m_auxVertices.size());
|
||||
lineArgs.m_colors = &skeletonColor;
|
||||
lineArgs.m_colorCount = 1;
|
||||
lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off;
|
||||
auxGeom->DrawLines(lineArgs);
|
||||
}
|
||||
|
||||
void AtomActorInstance::RenderEMFXDebugDraw(RPI::AuxGeomDraw* auxGeom)
|
||||
{
|
||||
EMotionFX::DebugDraw& debugDraw = EMotionFX::GetDebugDraw();
|
||||
debugDraw.Lock();
|
||||
EMotionFX::DebugDraw::ActorInstanceData* actorInstanceData = debugDraw.GetActorInstanceData(m_actorInstance);
|
||||
actorInstanceData->Lock();
|
||||
const AZStd::vector<EMotionFX::DebugDraw::Line>& lines = actorInstanceData->GetLines();
|
||||
if (lines.empty())
|
||||
{
|
||||
actorInstanceData->Unlock();
|
||||
debugDraw.Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
m_auxVertices.clear();
|
||||
m_auxVertices.reserve(lines.size() * 2);
|
||||
m_auxColors.clear();
|
||||
m_auxColors.reserve(m_auxVertices.size());
|
||||
|
||||
for (const EMotionFX::DebugDraw::Line& line : actorInstanceData->GetLines())
|
||||
{
|
||||
m_auxVertices.emplace_back(line.m_start);
|
||||
m_auxColors.emplace_back(line.m_startColor);
|
||||
m_auxVertices.emplace_back(line.m_end);
|
||||
m_auxColors.emplace_back(line.m_endColor);
|
||||
}
|
||||
|
||||
AZ_Assert(m_auxVertices.size() == m_auxColors.size(),
|
||||
"Number of vertices and number of colors need to match.");
|
||||
actorInstanceData->Unlock();
|
||||
debugDraw.Unlock();
|
||||
|
||||
RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs;
|
||||
lineArgs.m_verts = m_auxVertices.data();
|
||||
lineArgs.m_vertCount = static_cast<uint32_t>(m_auxVertices.size());
|
||||
lineArgs.m_colors = m_auxColors.data();
|
||||
lineArgs.m_colorCount = static_cast<uint32_t>(m_auxColors.size());
|
||||
lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off;
|
||||
auxGeom->DrawLines(lineArgs);
|
||||
}
|
||||
|
||||
AZ::Aabb AtomActorInstance::GetWorldBounds()
|
||||
{
|
||||
return m_worldAABB;
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace AZ
|
||||
class SkinnedMeshInputBuffers;
|
||||
class MeshFeatureProcessorInterface;
|
||||
class AtomActor;
|
||||
class AtomActorDebugDraw;
|
||||
|
||||
//! Render node for managing and rendering actor instances. Each Actor Component
|
||||
//! creates an ActorRenderNode. The render node is responsible for drawing meshes and
|
||||
@@ -85,8 +86,8 @@ namespace AZ
|
||||
|
||||
// RenderActorInstance overrides ...
|
||||
void OnTick(float timeDelta) override;
|
||||
void DebugDraw(const EMotionFX::ActorRenderFlagBitset& renderFlags);
|
||||
void UpdateBounds() override;
|
||||
void DebugDraw(const DebugOptions& debugOptions) override;
|
||||
void SetMaterials(const EMotionFX::Integration::ActorAsset::MaterialList& materialPerLOD) override { AZ_UNUSED(materialPerLOD); };
|
||||
void SetSkinningMethod(EMotionFX::Integration::SkinningMethod emfxSkinningMethod) override;
|
||||
SkinningMethod GetAtomSkinningMethod() const;
|
||||
@@ -184,12 +185,8 @@ namespace AZ
|
||||
void InitWrinkleMasks();
|
||||
void UpdateWrinkleMasks();
|
||||
|
||||
// Helper and debug geometry rendering
|
||||
void RenderSkeleton(RPI::AuxGeomDraw* auxGeom);
|
||||
void RenderEMFXDebugDraw(RPI::AuxGeomDraw* auxGeom);
|
||||
RPI::AuxGeomFeatureProcessorInterface* m_auxGeomFeatureProcessor = nullptr;
|
||||
AZStd::vector<AZ::Vector3> m_auxVertices;
|
||||
AZStd::vector<AZ::Color> m_auxColors;
|
||||
// Debug geometry rendering
|
||||
AZStd::unique_ptr<AtomActorDebugDraw> m_atomActorDebugDraw;
|
||||
|
||||
AZStd::intrusive_ptr<AZ::Render::SkinnedMeshInputBuffers> m_skinnedMeshInputBuffers = nullptr;
|
||||
AZStd::intrusive_ptr<SkinnedMeshInstance> m_skinnedMeshInstance;
|
||||
|
||||
@@ -206,6 +206,20 @@ namespace EMStudio
|
||||
return result;
|
||||
}
|
||||
|
||||
void AnimViewportRenderer::UpdateActorRenderFlag(EMotionFX::ActorRenderFlagBitset renderFlags)
|
||||
{
|
||||
for (AZ::Entity* entity : m_actorEntities)
|
||||
{
|
||||
EMotionFX::Integration::ActorComponent* actorComponent = entity->FindComponent<EMotionFX::Integration::ActorComponent>();
|
||||
if (!actorComponent)
|
||||
{
|
||||
AZ_Assert(false, "Found entity without actor component in the actor entity list.");
|
||||
continue;
|
||||
}
|
||||
actorComponent->SetRenderFlag(renderFlags);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimViewportRenderer::ResetEnvironment()
|
||||
{
|
||||
// Reset environment
|
||||
|
||||
@@ -52,6 +52,8 @@ namespace EMStudio
|
||||
//! Return the center position of the existing objects.
|
||||
AZ::Vector3 GetCharacterCenter() const;
|
||||
|
||||
void UpdateActorRenderFlag(EMotionFX::ActorRenderFlagBitset renderFlags);
|
||||
|
||||
private:
|
||||
|
||||
// This function resets the light, camera and other environment settings.
|
||||
@@ -79,10 +81,6 @@ namespace EMStudio
|
||||
|
||||
AZ::Entity* m_postProcessEntity = nullptr;
|
||||
AZ::Entity* m_iblEntity = nullptr;
|
||||
AZ::Entity* m_cameraEntity = nullptr;
|
||||
AZ::Component* m_cameraComponent = nullptr;
|
||||
AZ::Entity* m_modelEntity = nullptr;
|
||||
AZ::Data::AssetId m_modelAssetId;
|
||||
AZ::Entity* m_gridEntity = nullptr;
|
||||
AZStd::vector<AZ::Entity*> m_actorEntities;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
#include <Integration/Rendering/RenderFlag.h>
|
||||
|
||||
namespace EMStudio
|
||||
{
|
||||
@@ -35,6 +35,9 @@ namespace EMStudio
|
||||
|
||||
//! Set the camera view mode.
|
||||
virtual void SetCameraViewMode(CameraViewMode mode) = 0;
|
||||
|
||||
//! Toggle render option flag
|
||||
virtual void ToggleRenderFlag(EMotionFX::ActorRenderFlag flag) = 0;
|
||||
};
|
||||
|
||||
using AnimViewportRequestBus = AZ::EBus<AnimViewportRequests>;
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzQtComponents/Components/Widgets/ToolBar.h>
|
||||
|
||||
|
||||
namespace EMStudio
|
||||
{
|
||||
AnimViewportToolBar::AnimViewportToolBar(QWidget* parent)
|
||||
@@ -21,40 +20,107 @@ namespace EMStudio
|
||||
{
|
||||
AzQtComponents::ToolBar::addMainToolBarStyle(this);
|
||||
|
||||
// Add the camera button
|
||||
QToolButton* cameraButton = new QToolButton(this);
|
||||
QMenu* cameraMenu = new QMenu(cameraButton);
|
||||
|
||||
// Add the camera option
|
||||
const AZStd::vector<AZStd::pair<CameraViewMode, AZStd::string>> cameraOptionNames = {
|
||||
{ CameraViewMode::FRONT, "Front" }, { CameraViewMode::BACK, "Back" }, { CameraViewMode::TOP, "Top" },
|
||||
{ CameraViewMode::BOTTOM, "Bottom" }, { CameraViewMode::LEFT, "Left" }, { CameraViewMode::RIGHT, "Right" },
|
||||
};
|
||||
|
||||
for (const auto& pair : cameraOptionNames)
|
||||
// Add the render view options button
|
||||
QToolButton* renderOptionsButton = new QToolButton(this);
|
||||
{
|
||||
CameraViewMode mode = pair.first;
|
||||
cameraMenu->addAction(
|
||||
pair.second.c_str(),
|
||||
[mode]()
|
||||
{
|
||||
// Send the reset camera event.
|
||||
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::SetCameraViewMode, mode);
|
||||
});
|
||||
QMenu* contextMenu = new QMenu(renderOptionsButton);
|
||||
|
||||
renderOptionsButton->setText("Render Options");
|
||||
renderOptionsButton->setMenu(contextMenu);
|
||||
renderOptionsButton->setPopupMode(QToolButton::InstantPopup);
|
||||
renderOptionsButton->setVisible(true);
|
||||
renderOptionsButton->setIcon(QIcon(":/EMotionFXAtom/Visualization.svg"));
|
||||
addWidget(renderOptionsButton);
|
||||
|
||||
CreateViewOptionEntry(contextMenu, "Solid", EMotionFX::ActorRenderFlag::RENDER_SOLID);
|
||||
CreateViewOptionEntry(contextMenu, "Wireframe", EMotionFX::ActorRenderFlag::RENDER_WIREFRAME);
|
||||
CreateViewOptionEntry(contextMenu, "Lighting", EMotionFX::ActorRenderFlag::RENDER_LIGHTING);
|
||||
CreateViewOptionEntry(contextMenu, "Backface Culling", EMotionFX::ActorRenderFlag::RENDER_BACKFACECULLING);
|
||||
contextMenu->addSeparator();
|
||||
CreateViewOptionEntry(contextMenu, "Vertex Normals", EMotionFX::ActorRenderFlag::RENDER_VERTEXNORMALS);
|
||||
CreateViewOptionEntry(contextMenu, "Face Normals", EMotionFX::ActorRenderFlag::RENDER_FACENORMALS);
|
||||
CreateViewOptionEntry(contextMenu, "Tangents", EMotionFX::ActorRenderFlag::RENDER_TANGENTS);
|
||||
CreateViewOptionEntry(contextMenu, "Actor Bounding Boxes", EMotionFX::ActorRenderFlag::RENDER_AABB);
|
||||
contextMenu->addSeparator();
|
||||
CreateViewOptionEntry(contextMenu, "Line Skeleton", EMotionFX::ActorRenderFlag::RENDER_LINESKELETON);
|
||||
CreateViewOptionEntry(contextMenu, "Solid Skeleton", EMotionFX::ActorRenderFlag::RENDER_SKELETON);
|
||||
CreateViewOptionEntry(contextMenu, "Joint Names", EMotionFX::ActorRenderFlag::RENDER_NODENAMES);
|
||||
CreateViewOptionEntry(contextMenu, "Joint Orientations", EMotionFX::ActorRenderFlag::RENDER_NODEORIENTATION);
|
||||
CreateViewOptionEntry(contextMenu, "Actor Bind Pose", EMotionFX::ActorRenderFlag::RENDER_ACTORBINDPOSE);
|
||||
contextMenu->addSeparator();
|
||||
}
|
||||
|
||||
cameraMenu->addSeparator();
|
||||
cameraMenu->addAction("Reset Camera",
|
||||
[]()
|
||||
// Add the camera button
|
||||
QToolButton* cameraButton = new QToolButton(this);
|
||||
{
|
||||
QMenu* cameraMenu = new QMenu(cameraButton);
|
||||
|
||||
// Add the camera option
|
||||
const AZStd::vector<AZStd::pair<CameraViewMode, AZStd::string>> cameraOptionNames = {
|
||||
{ CameraViewMode::FRONT, "Front" }, { CameraViewMode::BACK, "Back" }, { CameraViewMode::TOP, "Top" },
|
||||
{ CameraViewMode::BOTTOM, "Bottom" }, { CameraViewMode::LEFT, "Left" }, { CameraViewMode::RIGHT, "Right" },
|
||||
};
|
||||
|
||||
for (const auto& pair : cameraOptionNames)
|
||||
{
|
||||
CameraViewMode mode = pair.first;
|
||||
cameraMenu->addAction(
|
||||
pair.second.c_str(),
|
||||
[mode]()
|
||||
{
|
||||
// Send the reset camera event.
|
||||
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::SetCameraViewMode, mode);
|
||||
});
|
||||
}
|
||||
|
||||
cameraMenu->addSeparator();
|
||||
cameraMenu->addAction(
|
||||
"Reset Camera",
|
||||
[]()
|
||||
{
|
||||
// Send the reset camera event.
|
||||
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::ResetCamera);
|
||||
});
|
||||
cameraButton->setMenu(cameraMenu);
|
||||
cameraButton->setText("Camera Option");
|
||||
cameraButton->setPopupMode(QToolButton::InstantPopup);
|
||||
cameraButton->setVisible(true);
|
||||
cameraButton->setIcon(QIcon(":/EMotionFXAtom/Camera_category.svg"));
|
||||
addWidget(cameraButton);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimViewportToolBar::CreateViewOptionEntry(
|
||||
QMenu* menu, const char* menuEntryName, uint32_t actionIndex, bool visible, char* iconFileName)
|
||||
{
|
||||
QAction* action = menu->addAction(
|
||||
menuEntryName,
|
||||
[actionIndex]()
|
||||
{
|
||||
// Send the reset camera event.
|
||||
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::ResetCamera);
|
||||
AnimViewportRequestBus::Broadcast(
|
||||
&AnimViewportRequestBus::Events::ToggleRenderFlag, (EMotionFX::ActorRenderFlag)actionIndex);
|
||||
});
|
||||
cameraButton->setMenu(cameraMenu);
|
||||
cameraButton->setText("Camera Option");
|
||||
cameraButton->setPopupMode(QToolButton::InstantPopup);
|
||||
cameraButton->setVisible(true);
|
||||
cameraButton->setIcon(QIcon(":/EMotionFXAtom/Camera_category.svg"));
|
||||
addWidget(cameraButton);
|
||||
action->setCheckable(true);
|
||||
action->setVisible(visible);
|
||||
|
||||
if (iconFileName)
|
||||
{
|
||||
action->setIcon(QIcon(iconFileName));
|
||||
}
|
||||
|
||||
m_actions[actionIndex] = action;
|
||||
}
|
||||
|
||||
void AnimViewportToolBar::SetRenderFlags(EMotionFX::ActorRenderFlagBitset renderFlags)
|
||||
{
|
||||
for (size_t i = 0; i < renderFlags.size(); ++i)
|
||||
{
|
||||
QAction* action = m_actions[i];
|
||||
if (action)
|
||||
{
|
||||
action->setChecked(renderFlags[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace EMStudio
|
||||
|
||||
@@ -11,8 +11,11 @@
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QAction>
|
||||
#include <QToolBar>
|
||||
#include <QMenu>
|
||||
#endif
|
||||
|
||||
#include <Integration/Rendering/RenderFlag.h>
|
||||
|
||||
namespace EMStudio
|
||||
{
|
||||
class AnimViewportToolBar : public QToolBar
|
||||
@@ -20,5 +23,13 @@ namespace EMStudio
|
||||
public:
|
||||
AnimViewportToolBar(QWidget* parent = nullptr);
|
||||
~AnimViewportToolBar() = default;
|
||||
|
||||
void SetRenderFlags(EMotionFX::ActorRenderFlagBitset renderFlags);
|
||||
|
||||
private:
|
||||
void CreateViewOptionEntry(
|
||||
QMenu* menu, const char* menuEntryName, uint32_t actionIndex, bool visible = true, char* iconFileName = nullptr);
|
||||
|
||||
QAction* m_actions[EMotionFX::ActorRenderFlag::NUM_RENDERFLAGS] = { nullptr };
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzFramework/Viewport/CameraInput.h>
|
||||
#include <Atom/RPI.Public/ViewportContext.h>
|
||||
#include <AtomToolsFramework/Viewport/ModularViewportCameraController.h>
|
||||
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
|
||||
|
||||
#include <EMStudio/AnimViewportWidget.h>
|
||||
#include <EMStudio/AnimViewportRenderer.h>
|
||||
@@ -32,6 +33,7 @@ namespace EMStudio
|
||||
|
||||
m_renderer = AZStd::make_unique<AnimViewportRenderer>(GetViewportContext());
|
||||
|
||||
LoadRenderFlags();
|
||||
SetupCameras();
|
||||
SetupCameraController();
|
||||
Reinit();
|
||||
@@ -41,6 +43,7 @@ namespace EMStudio
|
||||
|
||||
AnimViewportWidget::~AnimViewportWidget()
|
||||
{
|
||||
SaveRenderFlags();
|
||||
AnimViewportRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
@@ -50,7 +53,14 @@ namespace EMStudio
|
||||
{
|
||||
ResetCamera();
|
||||
}
|
||||
|
||||
m_renderer->Reinit();
|
||||
m_renderer->UpdateActorRenderFlag(m_renderFlags);
|
||||
}
|
||||
|
||||
EMotionFX::ActorRenderFlagBitset AnimViewportWidget::GetRenderFlags() const
|
||||
{
|
||||
return m_renderFlags;
|
||||
}
|
||||
|
||||
void AnimViewportWidget::SetupCameras()
|
||||
@@ -123,7 +133,7 @@ namespace EMStudio
|
||||
SetCameraViewMode(CameraViewMode::DEFAULT);
|
||||
}
|
||||
|
||||
void AnimViewportWidget::SetCameraViewMode([[maybe_unused]]CameraViewMode mode)
|
||||
void AnimViewportWidget::SetCameraViewMode(CameraViewMode mode)
|
||||
{
|
||||
// Set the camera view mode.
|
||||
const AZ::Vector3 targetPosition = m_renderer->GetCharacterCenter();
|
||||
@@ -155,4 +165,38 @@ namespace EMStudio
|
||||
}
|
||||
GetViewportContext()->SetCameraTransform(AZ::Transform::CreateLookAt(cameraPosition, targetPosition));
|
||||
}
|
||||
|
||||
void AnimViewportWidget::ToggleRenderFlag(EMotionFX::ActorRenderFlag flag)
|
||||
{
|
||||
m_renderFlags[flag] = !m_renderFlags[flag];
|
||||
m_renderer->UpdateActorRenderFlag(m_renderFlags);
|
||||
}
|
||||
|
||||
void AnimViewportWidget::LoadRenderFlags()
|
||||
{
|
||||
AZStd::string renderFlagsFilename(EMStudioManager::GetInstance()->GetAppDataFolder());
|
||||
renderFlagsFilename += "AnimViewportRenderFlags.cfg";
|
||||
QSettings settings(renderFlagsFilename.c_str(), QSettings::IniFormat, this);
|
||||
|
||||
for (uint32 i = 0; i < EMotionFX::ActorRenderFlag::NUM_RENDERFLAGS; ++i)
|
||||
{
|
||||
QString name = QString(i);
|
||||
const bool isEnabled = settings.value(name).toBool();
|
||||
m_renderFlags[i] = isEnabled;
|
||||
}
|
||||
m_renderer->UpdateActorRenderFlag(m_renderFlags);
|
||||
}
|
||||
|
||||
void AnimViewportWidget::SaveRenderFlags()
|
||||
{
|
||||
AZStd::string renderFlagsFilename(EMStudioManager::GetInstance()->GetAppDataFolder());
|
||||
renderFlagsFilename += "AnimViewportRenderFlags.cfg";
|
||||
QSettings settings(renderFlagsFilename.c_str(), QSettings::IniFormat, this);
|
||||
|
||||
for (uint32 i = 0; i < EMotionFX::ActorRenderFlag::NUM_RENDERFLAGS; ++i)
|
||||
{
|
||||
QString name = QString(i);
|
||||
settings.setValue(name, (bool)m_renderFlags[i]);
|
||||
}
|
||||
}
|
||||
} // namespace EMStudio
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QSettings>
|
||||
#include <AtomToolsFramework/Viewport/RenderViewportWidget.h>
|
||||
#include <AzFramework/Viewport/CameraInput.h>
|
||||
#include <EMStudio/AnimViewportRequestBus.h>
|
||||
#include <Integration/Rendering/RenderFlag.h>
|
||||
|
||||
namespace EMStudio
|
||||
{
|
||||
@@ -25,14 +27,19 @@ namespace EMStudio
|
||||
AnimViewportRenderer* GetAnimViewportRenderer() { return m_renderer.get(); }
|
||||
|
||||
void Reinit(bool resetCamera = true);
|
||||
EMotionFX::ActorRenderFlagBitset GetRenderFlags() const;
|
||||
|
||||
private:
|
||||
void SetupCameras();
|
||||
void SetupCameraController();
|
||||
|
||||
void LoadRenderFlags();
|
||||
void SaveRenderFlags();
|
||||
|
||||
// AnimViewportRequestBus::Handler overrides
|
||||
void ResetCamera();
|
||||
void SetCameraViewMode(CameraViewMode mode);
|
||||
void ToggleRenderFlag(EMotionFX::ActorRenderFlag flag);
|
||||
|
||||
static constexpr float CameraDistance = 2.0f;
|
||||
|
||||
@@ -40,5 +47,6 @@ namespace EMStudio
|
||||
AZStd::shared_ptr<AzFramework::RotateCameraInput> m_rotateCamera;
|
||||
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_translateCamera;
|
||||
AZStd::shared_ptr<AzFramework::OrbitDollyScrollCameraInput> m_orbitDollyScrollCamera;
|
||||
EMotionFX::ActorRenderFlagBitset m_renderFlags;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -90,12 +90,14 @@ namespace EMStudio
|
||||
verticalLayout->setSpacing(1);
|
||||
verticalLayout->setMargin(0);
|
||||
|
||||
// Add the tool bar
|
||||
AnimViewportToolBar* toolBar = new AnimViewportToolBar(m_innerWidget);
|
||||
verticalLayout->addWidget(toolBar);
|
||||
|
||||
// Add the viewport widget
|
||||
m_animViewportWidget = new AnimViewportWidget(m_innerWidget);
|
||||
|
||||
// Add the tool bar
|
||||
AnimViewportToolBar* toolBar = new AnimViewportToolBar(m_innerWidget);
|
||||
toolBar->SetRenderFlags(m_animViewportWidget->GetRenderFlags());
|
||||
|
||||
verticalLayout->addWidget(toolBar);
|
||||
verticalLayout->addWidget(m_animViewportWidget);
|
||||
|
||||
// Register command callbacks.
|
||||
|
||||
@@ -17,4 +17,6 @@ set(FILES
|
||||
Source/AtomActor.cpp
|
||||
Source/AtomActorInstance.h
|
||||
Source/AtomActorInstance.cpp
|
||||
Source/AtomActorDebugDraw.h
|
||||
Source/AtomActorDebugDraw.cpp
|
||||
)
|
||||
|
||||
@@ -143,6 +143,7 @@ namespace Blast
|
||||
void BlastSystemComponent::Deactivate()
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Physics);
|
||||
AZ::Data::AssetBus::MultiHandler::BusDisconnect();
|
||||
CrySystemEventBus::Handler::BusDisconnect();
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
BlastSystemRequestBus::Handler::BusDisconnect();
|
||||
|
||||
@@ -85,9 +85,6 @@ namespace EMotionFX
|
||||
/// Detach from parent entity, if attached.
|
||||
virtual void DetachFromEntity() {}
|
||||
|
||||
/// Enables debug-drawing of the actor's root.
|
||||
virtual void DebugDrawRoot(bool /*enable*/) {}
|
||||
|
||||
/// Enables rendering of the actor.
|
||||
virtual bool GetRenderCharacter() const = 0;
|
||||
virtual void SetRenderCharacter(bool enable) = 0;
|
||||
|
||||
@@ -209,7 +209,6 @@ namespace EMotionFX
|
||||
->Event("GetJointTransform", &ActorComponentRequestBus::Events::GetJointTransform)
|
||||
->Event("AttachToEntity", &ActorComponentRequestBus::Events::AttachToEntity)
|
||||
->Event("DetachFromEntity", &ActorComponentRequestBus::Events::DetachFromEntity)
|
||||
->Event("DebugDrawRoot", &ActorComponentRequestBus::Events::DebugDrawRoot)
|
||||
->Event("GetRenderCharacter", &ActorComponentRequestBus::Events::GetRenderCharacter)
|
||||
->Event("SetRenderCharacter", &ActorComponentRequestBus::Events::SetRenderCharacter)
|
||||
->Event("GetRenderActorVisible", &ActorComponentRequestBus::Events::GetRenderActorVisible)
|
||||
@@ -238,8 +237,7 @@ namespace EMotionFX
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ActorComponent::ActorComponent(const Configuration* configuration)
|
||||
: m_debugDrawRoot(false)
|
||||
, m_sceneFinishSimHandler([this]([[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
|
||||
: m_sceneFinishSimHandler([this]([[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
|
||||
float fixedDeltatime)
|
||||
{
|
||||
if (m_actorInstance)
|
||||
@@ -252,6 +250,8 @@ namespace EMotionFX
|
||||
{
|
||||
m_configuration = *configuration;
|
||||
}
|
||||
|
||||
m_debugRenderFlags[RENDER_SOLID] = true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -341,12 +341,6 @@ namespace EMotionFX
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ActorComponent::DebugDrawRoot(bool enable)
|
||||
{
|
||||
m_debugDrawRoot = enable;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ActorComponent::GetRenderCharacter() const
|
||||
{
|
||||
@@ -400,6 +394,11 @@ namespace EMotionFX
|
||||
return m_sceneFinishSimHandler.IsConnected();
|
||||
}
|
||||
|
||||
void ActorComponent::SetRenderFlag(ActorRenderFlagBitset renderFlags)
|
||||
{
|
||||
m_debugRenderFlags = renderFlags;
|
||||
}
|
||||
|
||||
void ActorComponent::CheckActorCreation()
|
||||
{
|
||||
// Create actor instance.
|
||||
@@ -573,13 +572,13 @@ namespace EMotionFX
|
||||
m_actorInstance->SetIsVisible(isInCameraFrustum && m_configuration.m_renderCharacter);
|
||||
}
|
||||
|
||||
RenderActorInstance::DebugOptions debugOptions;
|
||||
debugOptions.m_drawAABB = m_configuration.m_renderBounds;
|
||||
debugOptions.m_drawSkeleton = m_configuration.m_renderSkeleton;
|
||||
debugOptions.m_drawRootTransform = m_debugDrawRoot;
|
||||
debugOptions.m_rootWorldTransform = GetEntity()->GetTransform()->GetWorldTM();
|
||||
debugOptions.m_emfxDebugDraw = true;
|
||||
m_renderActorInstance->DebugDraw(debugOptions);
|
||||
m_renderActorInstance->SetIsVisible(m_debugRenderFlags[RENDER_SOLID]);
|
||||
|
||||
// The configuration stores some debug option. When that is enabled, we override it on top of the render flags.
|
||||
m_debugRenderFlags[RENDER_AABB] = m_debugRenderFlags[RENDER_AABB] || m_configuration.m_renderBounds;
|
||||
m_debugRenderFlags[RENDER_SKELETON] = m_debugRenderFlags[RENDER_SKELETON] || m_configuration.m_renderSkeleton;
|
||||
m_debugRenderFlags[RENDER_EMFX_DEBUG] = true;
|
||||
m_renderActorInstance->DebugDraw(m_debugRenderFlags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,6 @@ namespace EMotionFX
|
||||
ActorInstance* GetActorInstance() override { return m_actorInstance.get(); }
|
||||
void AttachToEntity(AZ::EntityId targetEntityId, AttachmentType attachmentType) override;
|
||||
void DetachFromEntity() override;
|
||||
void DebugDrawRoot(bool enable) override;
|
||||
bool GetRenderCharacter() const override;
|
||||
void SetRenderCharacter(bool enable) override;
|
||||
bool GetRenderActorVisible() const override;
|
||||
@@ -181,6 +180,8 @@ namespace EMotionFX
|
||||
bool IsPhysicsSceneSimulationFinishEventConnected() const;
|
||||
AZ::Data::Asset<ActorAsset> GetActorAsset() const { return m_configuration.m_actorAsset; }
|
||||
|
||||
void SetRenderFlag(ActorRenderFlagBitset renderFlags);
|
||||
|
||||
private:
|
||||
// AZ::TransformNotificationBus::MultiHandler
|
||||
void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
|
||||
@@ -201,7 +202,7 @@ namespace EMotionFX
|
||||
AZStd::vector<AZ::EntityId> m_attachments;
|
||||
|
||||
AZStd::unique_ptr<RenderActorInstance> m_renderActorInstance;
|
||||
bool m_debugDrawRoot; ///< Enables drawing of actor root and facing.
|
||||
ActorRenderFlagBitset m_debugRenderFlags; ///< Actor debug render flag
|
||||
|
||||
AzPhysics::SceneEvents::OnSceneSimulationFinishHandler m_sceneFinishSimHandler;
|
||||
};
|
||||
|
||||
@@ -180,6 +180,7 @@ namespace EMotionFX
|
||||
, m_lodLevel(0)
|
||||
, m_actorAsset(AZ::Data::AssetLoadBehavior::NoLoad)
|
||||
{
|
||||
m_debugRenderFlags[RENDER_SOLID] = true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -604,11 +605,10 @@ namespace EMotionFX
|
||||
m_renderActorInstance->OnTick(deltaTime);
|
||||
m_renderActorInstance->UpdateBounds();
|
||||
|
||||
RenderActorInstance::DebugOptions debugOptions;
|
||||
debugOptions.m_drawAABB = m_renderBounds;
|
||||
debugOptions.m_drawSkeleton = m_renderSkeleton;
|
||||
debugOptions.m_emfxDebugDraw = true;
|
||||
m_renderActorInstance->DebugDraw(debugOptions);
|
||||
m_debugRenderFlags[RENDER_AABB] = m_renderBounds;
|
||||
m_debugRenderFlags[RENDER_SKELETON] = m_renderSkeleton;
|
||||
m_debugRenderFlags[RENDER_EMFX_DEBUG] = true;
|
||||
m_renderActorInstance->DebugDraw(m_debugRenderFlags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -951,5 +951,10 @@ namespace EMotionFX
|
||||
LmbrCentral::AttachmentComponentRequestBus::Event(attachment, &LmbrCentral::AttachmentComponentRequestBus::Events::Reattach, true);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorActorComponent::SetRenderFlag(ActorRenderFlagBitset renderFlags)
|
||||
{
|
||||
m_debugRenderFlags = renderFlags;
|
||||
}
|
||||
} //namespace Integration
|
||||
} // namespace EMotionFX
|
||||
|
||||
@@ -104,6 +104,8 @@ namespace EMotionFX
|
||||
ActorComponent::GetRequiredServices(required);
|
||||
}
|
||||
|
||||
void SetRenderFlag(ActorRenderFlagBitset renderFlags);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
private:
|
||||
@@ -162,6 +164,7 @@ namespace EMotionFX
|
||||
size_t m_lodLevel;
|
||||
ActorComponent::BoundingBoxConfiguration m_bboxConfig;
|
||||
bool m_forceUpdateJointsOOV = false;
|
||||
ActorRenderFlagBitset m_debugRenderFlags; ///< Actor debug render flag
|
||||
// \todo attachmentTarget node nr
|
||||
|
||||
// Note: LOD work in progress. For now we use one material instead of a list of material, because we don't have the support for LOD with multiple scene files.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <Integration/ActorComponentBus.h>
|
||||
#include <Integration/Assets/ActorAsset.h>
|
||||
#include <Integration/Rendering/RenderFlag.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
@@ -33,16 +34,7 @@ namespace EMotionFX
|
||||
virtual ~RenderActorInstance() = default;
|
||||
|
||||
virtual void OnTick(float timeDelta) = 0;
|
||||
|
||||
struct DebugOptions
|
||||
{
|
||||
bool m_drawAABB = false;
|
||||
bool m_drawSkeleton = false;
|
||||
bool m_drawRootTransform = false;
|
||||
AZ::Transform m_rootWorldTransform = AZ::Transform::CreateIdentity();
|
||||
bool m_emfxDebugDraw = false;
|
||||
};
|
||||
virtual void DebugDraw(const DebugOptions& debugOptions) = 0;
|
||||
virtual void DebugDraw(const EMotionFX::ActorRenderFlagBitset& renderFlags) = 0;
|
||||
|
||||
SkinningMethod GetSkinningMethod() const;
|
||||
virtual void SetSkinningMethod(SkinningMethod skinningMethod);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/containers/bitset.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
enum ActorRenderFlag
|
||||
{
|
||||
RENDER_SOLID = 0,
|
||||
RENDER_WIREFRAME = 1,
|
||||
RENDER_LIGHTING = 2,
|
||||
RENDER_SHADOWS = 3,
|
||||
RENDER_FACENORMALS = 4,
|
||||
RENDER_VERTEXNORMALS = 5,
|
||||
RENDER_TANGENTS = 6,
|
||||
RENDER_AABB = 7,
|
||||
RENDER_SKELETON = 8,
|
||||
RENDER_LINESKELETON = 9,
|
||||
RENDER_NODEORIENTATION = 10,
|
||||
RENDER_NODENAMES = 11,
|
||||
RENDER_GRID = 12,
|
||||
RENDER_BACKFACECULLING = 13,
|
||||
RENDER_ACTORBINDPOSE = 14,
|
||||
RENDER_RAGDOLL_COLLIDERS = 15,
|
||||
RENDER_RAGDOLL_JOINTLIMITS = 16,
|
||||
RENDER_HITDETECTION_COLLIDERS = 17,
|
||||
RENDER_USE_GRADIENTBACKGROUND = 18,
|
||||
RENDER_MOTIONEXTRACTION = 19,
|
||||
RENDER_CLOTH_COLLIDERS = 20,
|
||||
RENDER_SIMULATEDOBJECT_COLLIDERS = 21,
|
||||
RENDER_SIMULATEJOINTS = 22,
|
||||
RENDER_EMFX_DEBUG = 23,
|
||||
NUM_RENDERFLAGS = 24
|
||||
};
|
||||
|
||||
using ActorRenderFlagBitset = AZStd::bitset<ActorRenderFlag::NUM_RENDERFLAGS>;
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <Integration/Assets/ActorAsset.h>
|
||||
#include <Integration/Rendering/RenderBackend.h>
|
||||
#include <Integration/Rendering/RenderActor.h>
|
||||
#include <Integration/Rendering/RenderFlag.h>
|
||||
#include <Integration/Rendering/RenderActorInstance.h>
|
||||
#include <Integration/Rendering/RenderBackendManager.h>
|
||||
#include <Integration/System/SystemCommon.h>
|
||||
@@ -64,7 +65,7 @@ namespace EMotionFX
|
||||
}
|
||||
|
||||
MOCK_METHOD1(OnTick, void(float));
|
||||
MOCK_METHOD1(DebugDraw, void(const DebugOptions&));
|
||||
MOCK_METHOD1(DebugDraw, void(const EMotionFX::ActorRenderFlagBitset&));
|
||||
MOCK_CONST_METHOD0(IsVisible, bool());
|
||||
MOCK_METHOD1(SetIsVisible, void(bool));
|
||||
MOCK_METHOD1(SetMaterials, void(const ActorAsset::MaterialList&));
|
||||
|
||||
@@ -9,43 +9,40 @@
|
||||
#include "BundlingSystemComponent.h"
|
||||
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Serialization/Utils.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
#include <AzFramework/Asset/AssetBundleManifest.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
|
||||
#include <ISystem.h>
|
||||
#include <IConsole.h>
|
||||
|
||||
#include <AzFramework/Archive/IArchive.h>
|
||||
|
||||
|
||||
namespace LmbrCentral
|
||||
{
|
||||
const char bundleRoot[] = "@products@";
|
||||
|
||||
// Calls the LoadBundles method
|
||||
static void ConsoleCommandLoadBundles(const AZ::ConsoleCommandContainer& commandArgs);
|
||||
// Calls the UnloadBundles method
|
||||
static void ConsoleCommandUnloadBundles(const AZ::ConsoleCommandContainer& commandArgs);
|
||||
|
||||
AZ_CONSOLEFREEFUNC("loadbundles", ConsoleCommandLoadBundles, AZ::ConsoleFunctorFlags::Null, "Load Asset Bundles");
|
||||
AZ_CONSOLEFREEFUNC("unloadbundles", ConsoleCommandUnloadBundles, AZ::ConsoleFunctorFlags::Null, "Unload Asset Bundles");
|
||||
|
||||
void BundlingSystemComponent::Activate()
|
||||
{
|
||||
BundlingSystemRequestBus::Handler::BusConnect();
|
||||
CrySystemEventBus::Handler::BusConnect();
|
||||
AZ::IO::ArchiveNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void BundlingSystemComponent::Deactivate()
|
||||
{
|
||||
AZ::IO::ArchiveNotificationBus::Handler::BusDisconnect();
|
||||
CrySystemEventBus::Handler::BusDisconnect();
|
||||
BundlingSystemRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void BundlingSystemComponent::OnCrySystemInitialized(ISystem& system, const SSystemInitParams& systemInitParams)
|
||||
{
|
||||
AZ_UNUSED(systemInitParams);
|
||||
|
||||
system.GetIConsole()->AddCommand("loadbundles", ConsoleCommandLoadBundles);
|
||||
system.GetIConsole()->AddCommand("unloadbundles", ConsoleCommandUnloadBundles);
|
||||
}
|
||||
|
||||
void BundlingSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
@@ -58,7 +55,7 @@ namespace LmbrCentral
|
||||
|
||||
AZStd::vector<AZStd::string> BundlingSystemComponent::GetBundleList(const char* bundlePath, const char* bundleExtension) const
|
||||
{
|
||||
AZStd::string fileFilter{ AZStd::string::format("*%s",bundleExtension) };
|
||||
AZStd::string fileFilter{ AZStd::string::format("*%s", bundleExtension) };
|
||||
AZStd::vector<AZStd::string> bundleList;
|
||||
|
||||
AZ::IO::FileIOBase::GetInstance()->FindFiles(bundlePath, fileFilter.c_str(), [&bundleList](const char* foundPath) -> bool
|
||||
@@ -73,29 +70,28 @@ namespace LmbrCentral
|
||||
return bundleList;
|
||||
}
|
||||
|
||||
void BundlingSystemComponent::ConsoleCommandLoadBundles(IConsoleCmdArgs* pCmdArgs)
|
||||
void ConsoleCommandLoadBundles(const AZ::ConsoleCommandContainer& commandArgs)
|
||||
{
|
||||
const char defaultBundleFolder[] = "bundles";
|
||||
const char defaultBundleExtension[] = ".pak";
|
||||
|
||||
const char* bundleFolder = pCmdArgs->GetArgCount() > 1 ? pCmdArgs->GetArg(1) : defaultBundleFolder;
|
||||
const char* bundleExtension = pCmdArgs->GetArgCount() > 2 ? pCmdArgs->GetArg(2) : defaultBundleExtension;
|
||||
AZ::CVarFixedString bundleFolder = commandArgs.size() > 0 ? AZ::CVarFixedString(commandArgs[0]) : defaultBundleFolder;
|
||||
AZ::CVarFixedString bundleExtension = commandArgs.size() > 1 ? AZ::CVarFixedString(commandArgs[1]) : defaultBundleExtension;
|
||||
|
||||
BundlingSystemRequestBus::Broadcast(&BundlingSystemRequestBus::Events::LoadBundles, bundleFolder, bundleExtension);
|
||||
BundlingSystemRequestBus::Broadcast(&BundlingSystemRequestBus::Events::LoadBundles, bundleFolder.c_str(), bundleExtension.c_str());
|
||||
}
|
||||
|
||||
void BundlingSystemComponent::ConsoleCommandUnloadBundles(IConsoleCmdArgs* pCmdArgs)
|
||||
void ConsoleCommandUnloadBundles([[maybe_unused]] const AZ::ConsoleCommandContainer& commandArgs)
|
||||
{
|
||||
AZ_UNUSED(pCmdArgs);
|
||||
BundlingSystemRequestBus::Broadcast(&BundlingSystemRequestBus::Events::UnloadBundles);
|
||||
}
|
||||
|
||||
void BundlingSystemComponent::UnloadBundles()
|
||||
{
|
||||
ISystem* crySystem{ GetISystem() };
|
||||
if (!crySystem)
|
||||
auto archive = AZ::Interface<AZ::IO::IArchive>::Get();
|
||||
if (!archive)
|
||||
{
|
||||
AZ_Error("BundlingSystem", false, "Couldn't Get ISystem to unload bundles!");
|
||||
AZ_Error("BundlingSystem", false, "Couldn't Get IArchive to load bundles!");
|
||||
return;
|
||||
}
|
||||
if (!m_bundleModeBundles.size())
|
||||
@@ -106,7 +102,7 @@ namespace LmbrCentral
|
||||
AZStd::lock_guard<AZStd::mutex> openBundleLock(m_bundleModeMutex);
|
||||
for (const auto& thisBundle : m_bundleModeBundles)
|
||||
{
|
||||
if (crySystem->GetIPak()->ClosePack(thisBundle.c_str()))
|
||||
if (archive->ClosePack(thisBundle.c_str()))
|
||||
{
|
||||
AZ_TracePrintf("BundlingSystem", "Unloaded %s\n",thisBundle.c_str());
|
||||
}
|
||||
@@ -128,15 +124,8 @@ namespace LmbrCentral
|
||||
return;
|
||||
}
|
||||
|
||||
ISystem* crySystem{ GetISystem() };
|
||||
if (!crySystem)
|
||||
{
|
||||
AZ_Error("BundlingSystem", false, "Couldn't Get ISystem to load bundles!");
|
||||
return;
|
||||
}
|
||||
|
||||
auto cryPak = crySystem->GetIPak();
|
||||
if (!cryPak)
|
||||
auto archive = AZ::Interface<AZ::IO::IArchive>::Get();
|
||||
if (!archive)
|
||||
{
|
||||
AZ_Error("BundlingSystem", false, "Couldn't Get IArchive to load bundles!");
|
||||
return;
|
||||
@@ -152,8 +141,8 @@ namespace LmbrCentral
|
||||
}
|
||||
}
|
||||
AZStd::string bundlePath;
|
||||
AzFramework::StringFunc::Path::Join(bundleRoot, thisBundle.c_str(), bundlePath);
|
||||
if (cryPak->OpenPack(bundleRoot, thisBundle.c_str()))
|
||||
AZ::StringFunc::Path::Join(bundleRoot, thisBundle.c_str(), bundlePath);
|
||||
if (archive->OpenPack(bundleRoot, thisBundle.c_str()))
|
||||
{
|
||||
AZ_TracePrintf("BundlingSystem", "Loaded bundle %s\n",bundlePath.c_str());
|
||||
m_bundleModeBundles.emplace_back(AZStd::move(bundlePath));
|
||||
@@ -230,28 +219,21 @@ namespace LmbrCentral
|
||||
|
||||
void BundlingSystemComponent::OpenDependentBundles(const char* bundleName, AZStd::shared_ptr<AzFramework::AssetBundleManifest> bundleManifest)
|
||||
{
|
||||
ISystem* crySystem{ GetISystem() };
|
||||
if (!crySystem)
|
||||
{
|
||||
AZ_Error("BundlingSystem", false, "Couldn't Get ISystem to load dependent bundles for %s", bundleName);
|
||||
return;
|
||||
}
|
||||
|
||||
auto cryPak{ crySystem->GetIPak() };
|
||||
if (!cryPak)
|
||||
auto archive = AZ::Interface<AZ::IO::IArchive>::Get();
|
||||
if (!archive)
|
||||
{
|
||||
AZ_Error("BundlingSystem", false, "Couldn't Get IArchive to load dependent bundles for %s", bundleName);
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::string folderPath;
|
||||
AzFramework::StringFunc::Path::GetFolderPath(bundleName, folderPath);
|
||||
AZ::StringFunc::Path::GetFolderPath(bundleName, folderPath);
|
||||
for (const auto& thisBundle : bundleManifest->GetDependentBundleNames())
|
||||
{
|
||||
AZStd::string bundlePath;
|
||||
AzFramework::StringFunc::Path::Join(folderPath.c_str(), thisBundle.c_str(), bundlePath);
|
||||
AZ::StringFunc::Path::Join(folderPath.c_str(), thisBundle.c_str(), bundlePath);
|
||||
|
||||
if (!cryPak->OpenPack(bundleRoot, bundlePath.c_str()))
|
||||
if (!archive->OpenPack(bundleRoot, bundlePath.c_str()))
|
||||
{
|
||||
// We're not bailing here intentionally - try to open the remaining bundles
|
||||
AZ_Warning("BundlingSystem", false, "Failed to open dependent bundle %s of bundle %s", bundlePath.c_str(), bundleName);
|
||||
@@ -300,28 +282,21 @@ namespace LmbrCentral
|
||||
|
||||
void BundlingSystemComponent::CloseDependentBundles(const char* bundleName, AZStd::shared_ptr<AzFramework::AssetBundleManifest> bundleManifest)
|
||||
{
|
||||
ISystem* crySystem{ GetISystem() };
|
||||
if (!crySystem)
|
||||
{
|
||||
AZ_Error("BundlingSystem", false, "Couldn't get ISystem to close dependent bundles for %s", bundleName);
|
||||
return;
|
||||
}
|
||||
|
||||
auto cryPak{ crySystem->GetIPak() };
|
||||
if (!cryPak)
|
||||
auto archive = AZ::Interface<AZ::IO::IArchive>::Get();
|
||||
if (!archive)
|
||||
{
|
||||
AZ_Error("BundlingSystem", false, "Couldn't get IArchive to close dependent bundles for %s", bundleName);
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::string folderPath;
|
||||
AzFramework::StringFunc::Path::GetFolderPath(bundleName, folderPath);
|
||||
AZ::StringFunc::Path::GetFolderPath(bundleName, folderPath);
|
||||
for (const auto& thisBundle : bundleManifest->GetDependentBundleNames())
|
||||
{
|
||||
AZStd::string bundlePath;
|
||||
AzFramework::StringFunc::Path::Join(folderPath.c_str(), thisBundle.c_str(), bundlePath);
|
||||
AZ::StringFunc::Path::Join(folderPath.c_str(), thisBundle.c_str(), bundlePath);
|
||||
|
||||
if (!cryPak->ClosePack(bundlePath.c_str()))
|
||||
if (!archive->ClosePack(bundlePath.c_str()))
|
||||
{
|
||||
// We're not bailing here intentionally - try to close the remaining bundles
|
||||
AZ_Warning("BundlingSystem", false, "Failed to close dependent bundle %s of bundle %s", bundlePath.c_str(), bundleName);
|
||||
|
||||
@@ -19,11 +19,8 @@
|
||||
|
||||
#include <LmbrCentral/Bundling/BundlingSystemComponentBus.h>
|
||||
|
||||
#include <CrySystemBus.h>
|
||||
#include <AzFramework/Archive/ArchiveBus.h>
|
||||
|
||||
struct IConsoleCmdArgs;
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class AssetBundleManifest;
|
||||
@@ -42,10 +39,9 @@ namespace LmbrCentral
|
||||
* System component for managing bundles
|
||||
*/
|
||||
class BundlingSystemComponent
|
||||
: public AZ::Component,
|
||||
public BundlingSystemRequestBus::Handler,
|
||||
public CrySystemEventBus::Handler,
|
||||
public AZ::IO::ArchiveNotificationBus::Handler
|
||||
: public AZ::Component
|
||||
, public BundlingSystemRequestBus::Handler
|
||||
, public AZ::IO::ArchiveNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(BundlingSystemComponent, "{0FB7153D-EE80-4B1C-9584-134270401AAF}");
|
||||
@@ -70,13 +66,6 @@ namespace LmbrCentral
|
||||
void BundleOpened(const char* bundleName, AZStd::shared_ptr<AzFramework::AssetBundleManifest> bundleManifest, const char* nextBundle, AZStd::shared_ptr<AzFramework::AssetRegistry> bundleCatalog) override;
|
||||
void BundleClosed(const char* bundleName) override;
|
||||
|
||||
// CrySystemEventBus
|
||||
void OnCrySystemInitialized(ISystem& system, const SSystemInitParams& systemInitParams) override;
|
||||
|
||||
// Calls the LoadBundles method
|
||||
static void ConsoleCommandLoadBundles(IConsoleCmdArgs* pCmdArgs);
|
||||
// Calls the UnloadBundles method
|
||||
static void ConsoleCommandUnloadBundles(IConsoleCmdArgs* pCmdArgs);
|
||||
|
||||
AZStd::vector<AZStd::string> GetBundleList(const char* bundlePath, const char* bundleExtension) const;
|
||||
|
||||
|
||||
@@ -84,8 +84,6 @@
|
||||
|
||||
namespace LmbrCentral
|
||||
{
|
||||
static const char* s_assetCatalogFilename = "assetcatalog.xml";
|
||||
|
||||
using LmbrCentralAllocatorScope = AZ::AllocatorScope<AZ::LegacyAllocator>;
|
||||
|
||||
// This component boots the required allocators for LmbrCentral everywhere but AssetBuilders
|
||||
@@ -354,8 +352,7 @@ namespace LmbrCentral
|
||||
AZ_Assert(AZ::Data::AssetManager::IsReady(), "Asset manager isn't ready!");
|
||||
|
||||
// Add asset types and extensions to AssetCatalog. Uses "AssetCatalogService".
|
||||
auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler();
|
||||
if (assetCatalog)
|
||||
if (auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler(); assetCatalog)
|
||||
{
|
||||
assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo<AZ::ScriptAsset>::Uuid());
|
||||
assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo<MaterialAsset>::Uuid());
|
||||
@@ -376,7 +373,6 @@ namespace LmbrCentral
|
||||
assetCatalog->AddExtension("cax");
|
||||
}
|
||||
|
||||
CrySystemEventBus::Handler::BusConnect();
|
||||
AZ::Data::AssetManagerNotificationBus::Handler::BusConnect();
|
||||
|
||||
|
||||
@@ -448,7 +444,6 @@ namespace LmbrCentral
|
||||
m_unhandledAssetInfo.clear();
|
||||
|
||||
AZ::Data::AssetManagerNotificationBus::Handler::BusDisconnect();
|
||||
CrySystemEventBus::Handler::BusDisconnect();
|
||||
|
||||
// AssetHandler's destructor calls Unregister()
|
||||
m_assetHandlers.clear();
|
||||
@@ -459,42 +454,6 @@ namespace LmbrCentral
|
||||
}
|
||||
m_allocatorShutdowns.clear();
|
||||
}
|
||||
|
||||
void LmbrCentralSystemComponent::OnCrySystemPreInitialize([[maybe_unused]] ISystem& system, [[maybe_unused]] const SSystemInitParams& systemInitParams)
|
||||
{
|
||||
EBUS_EVENT(AZ::Data::AssetCatalogRequestBus, StartMonitoringAssets);
|
||||
}
|
||||
|
||||
void LmbrCentralSystemComponent::OnCrySystemInitialized(ISystem& system, const SSystemInitParams& systemInitParams)
|
||||
{
|
||||
#if !defined(AZ_MONOLITHIC_BUILD)
|
||||
// When module is linked dynamically, we must set our gEnv pointer.
|
||||
// When module is linked statically, we'll share the application's gEnv pointer.
|
||||
gEnv = system.GetGlobalEnvironment();
|
||||
#endif
|
||||
|
||||
// Enable catalog now that application's asset root is set.
|
||||
if (system.GetGlobalEnvironment()->IsEditor())
|
||||
{
|
||||
// In the editor, we build the catalog by scanning the disk.
|
||||
if (systemInitParams.pUserCallback)
|
||||
{
|
||||
systemInitParams.pUserCallback->OnInitProgress("Refreshing asset catalog...");
|
||||
}
|
||||
}
|
||||
|
||||
// load the catalog from disk (supported over VFS).
|
||||
EBUS_EVENT(AZ::Data::AssetCatalogRequestBus, LoadCatalog, AZStd::string::format("@products@/%s", s_assetCatalogFilename).c_str());
|
||||
}
|
||||
|
||||
void LmbrCentralSystemComponent::OnCrySystemShutdown([[maybe_unused]] ISystem& system)
|
||||
{
|
||||
EBUS_EVENT(AZ::Data::AssetCatalogRequestBus, StopMonitoringAssets);
|
||||
|
||||
#if !defined(AZ_MONOLITHIC_BUILD)
|
||||
gEnv = nullptr;
|
||||
#endif
|
||||
}
|
||||
} // namespace LmbrCentral
|
||||
|
||||
#if !defined(LMBR_CENTRAL_EDITOR)
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
#include <CrySystemBus.h>
|
||||
|
||||
/*!
|
||||
* \namespace LmbrCentral
|
||||
* LmbrCentral ties together systems from CryEngine and systems from the AZ framework.
|
||||
@@ -49,7 +47,6 @@ namespace LmbrCentral
|
||||
*/
|
||||
class LmbrCentralSystemComponent
|
||||
: public AZ::Component
|
||||
, private CrySystemEventBus::Handler
|
||||
, private AZ::Data::AssetManagerNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
@@ -71,13 +68,6 @@ namespace LmbrCentral
|
||||
void Deactivate() override;
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// CrySystemEvents
|
||||
void OnCrySystemPreInitialize(ISystem& system, const SSystemInitParams& systemInitParams) override;
|
||||
void OnCrySystemInitialized(ISystem& system, const SSystemInitParams& systemInitParams) override;
|
||||
void OnCrySystemShutdown(ISystem& system) override;
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AZStd::vector<AZStd::unique_ptr<AZ::Data::AssetHandler> > m_assetHandlers;
|
||||
AZStd::vector<AZStd::unique_ptr<AZ::AssetTypeInfoBus::Handler> > m_unhandledAssetInfo;
|
||||
AZStd::vector<AZStd::function<void()>> m_allocatorShutdowns;
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// The Lifecycle events contains the name of the event as a string
|
||||
// ComponentApplication derived classes
|
||||
// will set these these keys to a JSON Object indicate an event has occured
|
||||
// A callback can be registered with the SettingsRegistry
|
||||
// to be notified when that key is set
|
||||
// The JSON object that is set will contain any payload data
|
||||
// related to the event
|
||||
{
|
||||
"O3DE" : {
|
||||
"Runtime": {
|
||||
"Application": {
|
||||
"LifecycleEvents": {
|
||||
"SystemComponentsActivated": {},
|
||||
"SystemComponentsDeactivated": {},
|
||||
"ReflectionManagerAvailable": {},
|
||||
"ReflectionManagerUnavailable": {},
|
||||
"SystemAllocatorCreated": {},
|
||||
"SystemAllocatorPendingDestruction": {},
|
||||
"SettingsRegistryAvailable": {},
|
||||
"SettingsRegistryUnavailable": {},
|
||||
"ConsoleAvailable": {},
|
||||
"ConsoleUnavailable": {},
|
||||
"GemsLoaded": {},
|
||||
"GemsUnloaded": {},
|
||||
"FileIOAvailable": {},
|
||||
"FileIOUnavailable": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
ly_install_directory(
|
||||
DIRECTORIES
|
||||
AssetGem
|
||||
CustomTool
|
||||
PythonGem
|
||||
DefaultGem
|
||||
DefaultProject
|
||||
MinimalProject
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
set(o3de_gem_path ${CMAKE_CURRENT_LIST_DIR})
|
||||
set(o3de_gem_json ${o3de_gem_path}/gem.json)
|
||||
o3de_read_json_key(o3de_gem_name ${o3de_gem_json} "gem_name")
|
||||
o3de_restricted_path(${o3de_gem_json} o3de_gem_restricted_path)
|
||||
|
||||
add_subdirectory(Code)
|
||||
@@ -0,0 +1,14 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
set(FILES
|
||||
Include/${Name}/${Name}Bus.h
|
||||
Source/${Name}ModuleInterface.h
|
||||
Source/${Name}EditorSystemComponent.cpp
|
||||
Source/${Name}EditorSystemComponent.h
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
set(FILES
|
||||
Source/${Name}EditorModule.cpp
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
set(FILES
|
||||
Tests/${Name}EditorTest.cpp
|
||||
)
|
||||
@@ -0,0 +1,76 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
# Currently we are in the Code folder: ${CMAKE_CURRENT_LIST_DIR}
|
||||
# Get the platform specific folder ${pal_dir} for the current folder: ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}
|
||||
# Note: ly_get_list_relative_pal_filename will take care of the details for us, as this may be a restricted platform
|
||||
# in which case it will see if that platform is present here or in the restricted folder.
|
||||
# i.e. It could here in our gem : Gems/${Name}/Code/Platform/<platorm_name> or
|
||||
# <restricted_folder>/<platform_name>/Gems/${Name}/Code
|
||||
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${o3de_gem_restricted_path} ${o3de_gem_path} ${o3de_gem_name})
|
||||
|
||||
# Now that we have the platform abstraction layer (PAL) folder for this folder, thats where we will find the
|
||||
# traits for this platform. Traits for a platform are defines for things like whether or not something in this gem
|
||||
# is supported by this platform.
|
||||
include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
|
||||
|
||||
|
||||
# If we are on a host platform, we want to add the host tools targets like the ${Name}.Editor target which
|
||||
# will also depend on ${Name}.Static
|
||||
if(PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
ly_add_target(
|
||||
NAME ${Name}.Editor.Static STATIC
|
||||
NAMESPACE Gem
|
||||
FILES_CMAKE
|
||||
${NameLower}_editor_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
PUBLIC
|
||||
Include
|
||||
BUILD_DEPENDENCIES
|
||||
PUBLIC
|
||||
AZ::AzToolsFramework
|
||||
)
|
||||
|
||||
ly_add_target(
|
||||
NAME ${Name}.Editor GEM_MODULE
|
||||
NAMESPACE Gem
|
||||
AUTOMOC
|
||||
FILES_CMAKE
|
||||
${NameLower}_editor_shared_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
PUBLIC
|
||||
Include
|
||||
BUILD_DEPENDENCIES
|
||||
PUBLIC
|
||||
Gem::${Name}.Editor.Static
|
||||
)
|
||||
|
||||
# By default, we will specify that the above target ${Name} would be used by
|
||||
# Tool and Builder type targets when this gem is enabled. If you don't want it
|
||||
# active in Tools or Builders by default, delete one of both of the following lines:
|
||||
ly_create_alias(NAME ${Name}.Tools NAMESPACE Gem TARGETS Gem::${Name}.Editor)
|
||||
ly_create_alias(NAME ${Name}.Builders NAMESPACE Gem TARGETS Gem::${Name}.Editor)
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
# Tests
|
||||
################################################################################
|
||||
# See if globally, tests are supported
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
# We globally support tests, see if we support tests on this platform for ${Name}.Static
|
||||
|
||||
# If we are a host platform we want to add tools test like editor tests here
|
||||
if(PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,40 @@
|
||||
// {BEGIN_LICENSE}
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
// {END_LICENSE}
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
|
||||
namespace ${SanitizedCppName}
|
||||
{
|
||||
class ${SanitizedCppName}Requests
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(${SanitizedCppName}Requests, "{${Random_Uuid}}");
|
||||
virtual ~${SanitizedCppName}Requests() = default;
|
||||
// Put your public methods here
|
||||
};
|
||||
|
||||
class ${SanitizedCppName}BusTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
using ${SanitizedCppName}RequestBus = AZ::EBus<${SanitizedCppName}Requests, ${SanitizedCppName}BusTraits>;
|
||||
using ${SanitizedCppName}Interface = AZ::Interface<${SanitizedCppName}Requests>;
|
||||
|
||||
} // namespace ${SanitizedCppName}
|
||||
@@ -0,0 +1,15 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
# Platform specific files for Linux
|
||||
# i.e. ../Source/Linux/${Name}Linux.cpp
|
||||
# ../Source/Linux/${Name}Linux.h
|
||||
# ../Include/Linux/${Name}Linux.h
|
||||
|
||||
set(FILES
|
||||
)
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
# Platform specific files for Linux
|
||||
# i.e. ../Source/Linux/${Name}Linux.cpp
|
||||
# ../Source/Linux/${Name}Linux.h
|
||||
# ../Include/Linux/${Name}Linux.h
|
||||
|
||||
set(FILES
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
set(PAL_TRAIT_${NameUpper}_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_${NameUpper}_TEST_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_${NameUpper}_EDITOR_TEST_SUPPORTED TRUE)
|
||||
@@ -0,0 +1,15 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
# Platform specific files for Mac
|
||||
# i.e. ../Source/Mac/${Name}Mac.cpp
|
||||
# ../Source/Mac/${Name}Mac.h
|
||||
# ../Include/Mac/${Name}Mac.h
|
||||
|
||||
set(FILES
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
# Platform specific files for Mac
|
||||
# i.e. ../Source/Mac/${Name}Mac.cpp
|
||||
# ../Source/Mac/${Name}Mac.h
|
||||
# ../Include/Mac/${Name}Mac.h
|
||||
|
||||
set(FILES
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
set(PAL_TRAIT_${NameUpper}_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_${NameUpper}_TEST_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_${NameUpper}_EDITOR_TEST_SUPPORTED TRUE)
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
# Platform specific files for Windows
|
||||
# i.e. ../Source/Windows/${Name}Windows.cpp
|
||||
# ../Source/Windows/${Name}Windows.h
|
||||
# ../Include/Windows/${Name}Windows.h
|
||||
|
||||
set(FILES
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
# Platform specific files for Windows
|
||||
# i.e. ../Source/Windows/${Name}Windows.cpp
|
||||
# ../Source/Windows/${Name}Windows.h
|
||||
# ../Include/Windows/${Name}Windows.h
|
||||
|
||||
set(FILES
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
# {BEGIN_LICENSE}
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
# {END_LICENSE}
|
||||
|
||||
set(PAL_TRAIT_${NameUpper}_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_${NameUpper}_TEST_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_${NameUpper}_EDITOR_TEST_SUPPORTED TRUE)
|
||||
@@ -0,0 +1,47 @@
|
||||
// {BEGIN_LICENSE}
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
// {END_LICENSE}
|
||||
|
||||
#include <${Name}ModuleInterface.h>
|
||||
#include <${Name}EditorSystemComponent.h>
|
||||
|
||||
namespace ${SanitizedCppName}
|
||||
{
|
||||
class ${SanitizedCppName}EditorModule
|
||||
: public ${SanitizedCppName}ModuleInterface
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(${SanitizedCppName}EditorModule, "${ModuleClassId}", ${SanitizedCppName}ModuleInterface);
|
||||
AZ_CLASS_ALLOCATOR(${SanitizedCppName}EditorModule, AZ::SystemAllocator, 0);
|
||||
|
||||
${SanitizedCppName}EditorModule()
|
||||
{
|
||||
// Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
|
||||
// Add ALL components descriptors associated with this gem to m_descriptors.
|
||||
// This will associate the AzTypeInfo information for the components with the the SerializeContext, BehaviorContext and EditContext.
|
||||
// This happens through the [MyComponent]::Reflect() function.
|
||||
m_descriptors.insert(m_descriptors.end(), {
|
||||
${SanitizedCppName}EditorSystemComponent::CreateDescriptor(),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add required SystemComponents to the SystemEntity.
|
||||
* Non-SystemComponents should not be added here
|
||||
*/
|
||||
AZ::ComponentTypeList GetRequiredSystemComponents() const override
|
||||
{
|
||||
return AZ::ComponentTypeList {
|
||||
azrtti_typeid<${SanitizedCppName}EditorSystemComponent>(),
|
||||
};
|
||||
}
|
||||
};
|
||||
}// namespace ${SanitizedCppName}
|
||||
|
||||
AZ_DECLARE_MODULE_CLASS(Gem_${SanitizedCppName}, ${SanitizedCppName}::${SanitizedCppName}EditorModule)
|
||||
@@ -0,0 +1,70 @@
|
||||
// {BEGIN_LICENSE}
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
// {END_LICENSE}
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <${Name}EditorSystemComponent.h>
|
||||
|
||||
namespace ${SanitizedCppName}
|
||||
{
|
||||
void ${SanitizedCppName}EditorSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<${SanitizedCppName}EditorSystemComponent, AZ::Component>();
|
||||
}
|
||||
}
|
||||
|
||||
${SanitizedCppName}EditorSystemComponent::${SanitizedCppName}EditorSystemComponent()
|
||||
{
|
||||
if (${SanitizedCppName}Interface::Get() == nullptr)
|
||||
{
|
||||
${SanitizedCppName}Interface::Register(this);
|
||||
}
|
||||
}
|
||||
|
||||
${SanitizedCppName}EditorSystemComponent::~${SanitizedCppName}EditorSystemComponent()
|
||||
{
|
||||
if (${SanitizedCppName}Interface::Get() == this)
|
||||
{
|
||||
${SanitizedCppName}Interface::Unregister(this);
|
||||
}
|
||||
}
|
||||
|
||||
void ${SanitizedCppName}EditorSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
{
|
||||
provided.push_back(AZ_CRC_CE("${SanitizedCppName}EditorService"));
|
||||
}
|
||||
|
||||
void ${SanitizedCppName}EditorSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC_CE("${SanitizedCppName}EditorService"));
|
||||
}
|
||||
|
||||
void ${SanitizedCppName}EditorSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
}
|
||||
|
||||
void ${SanitizedCppName}EditorSystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
||||
{
|
||||
}
|
||||
|
||||
void ${SanitizedCppName}EditorSystemComponent::Activate()
|
||||
{
|
||||
${SanitizedCppName}RequestBus::Handler::BusConnect();
|
||||
AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void ${SanitizedCppName}EditorSystemComponent::Deactivate()
|
||||
{
|
||||
AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
|
||||
${SanitizedCppName}RequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
} // namespace ${SanitizedCppName}
|
||||
@@ -0,0 +1,42 @@
|
||||
// {BEGIN_LICENSE}
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
// {END_LICENSE}
|
||||
|
||||
#pragma once
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <${Name}/${Name}Bus.h>
|
||||
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
|
||||
namespace ${SanitizedCppName}
|
||||
{
|
||||
/// System component for ${SanitizedCppName} editor
|
||||
class ${SanitizedCppName}EditorSystemComponent
|
||||
: public ${SanitizedCppName}RequestBus::Handler
|
||||
, private AzToolsFramework::EditorEvents::Bus::Handler
|
||||
, public AZ::Component
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(${SanitizedCppName}EditorSystemComponent, "${EditorSysCompClassId}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
${SanitizedCppName}EditorSystemComponent();
|
||||
~${SanitizedCppName}EditorSystemComponent();
|
||||
|
||||
private:
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
|
||||
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
|
||||
|
||||
// AZ::Component
|
||||
void Activate();
|
||||
void Deactivate();
|
||||
};
|
||||
} // namespace ${SanitizedCppName}
|
||||
@@ -0,0 +1,36 @@
|
||||
// {BEGIN_LICENSE}
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
// {END_LICENSE}
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Module/Module.h>
|
||||
|
||||
namespace ${SanitizedCppName}
|
||||
{
|
||||
class ${SanitizedCppName}ModuleInterface
|
||||
: public AZ::Module
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(${SanitizedCppName}ModuleInterface, "{${Random_Uuid}}", AZ::Module);
|
||||
AZ_CLASS_ALLOCATOR(${SanitizedCppName}ModuleInterface, AZ::SystemAllocator, 0);
|
||||
|
||||
${SanitizedCppName}ModuleInterface()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Add required SystemComponents to the SystemEntity.
|
||||
*/
|
||||
AZ::ComponentTypeList GetRequiredSystemComponents() const override
|
||||
{
|
||||
return AZ::ComponentTypeList{
|
||||
};
|
||||
}
|
||||
};
|
||||
}// namespace ${SanitizedCppName}
|
||||
@@ -0,0 +1,13 @@
|
||||
// {BEGIN_LICENSE}
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
// {END_LICENSE}
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
|
||||
AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);
|
||||
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
# -------------------------------------------------------------------------
|
||||
"""${SanitizedCppName}\\editor\\scripts\\${SanitizedCppName}_dialog.py
|
||||
Generated from O3DE PythonGem Template"""
|
||||
|
||||
import azlmbr
|
||||
from shiboken2 import wrapInstance, getCppPointer
|
||||
from PySide2 import QtCore, QtWidgets, QtGui
|
||||
from PySide2.QtCore import QEvent, Qt
|
||||
from PySide2.QtWidgets import QVBoxLayout, QAction, QDialog, QHeaderView, QLabel, QLineEdit, QPushButton, QSplitter, QTreeWidget, QTreeWidgetItem, QWidget, QAbstractButton
|
||||
|
||||
# Once PySide2 has been bootstrapped, register our ${SanitizedCppName}Dialog with the Editor
|
||||
|
||||
class ${SanitizedCppName}Dialog(QDialog):
|
||||
def __init__(self, parent=None):
|
||||
super(${SanitizedCppName}Dialog, self).__init__(parent)
|
||||
|
||||
self.setObjectName("${SanitizedCppName}Dialog")
|
||||
|
||||
self.setWindowTitle("HelloWorld, ${SanitizedCppName} Dialog")
|
||||
|
||||
self.mainLayout = QVBoxLayout(self)
|
||||
|
||||
self.introLabel = QLabel("Put your cool stuff here!")
|
||||
|
||||
self.mainLayout.addWidget(self.introLabel, 0, Qt.AlignCenter)
|
||||
|
||||
self.helpText = str("For help getting started,"
|
||||
"visit the <a href=\"https://o3de.org/docs/tools-ui/ui-dev-intro/\">UI Development</a> documentation<br/>"
|
||||
"or come ask a question in the <a href=\"https://discord.gg/R77Wss3kHe\">sig-ui-ux channel</a> on Discord")
|
||||
|
||||
self.helpLabel = QLabel()
|
||||
self.helpLabel.setTextFormat(Qt.RichText)
|
||||
self.helpLabel.setText(self.helpText)
|
||||
self.helpLabel.setOpenExternalLinks(True)
|
||||
|
||||
self.mainLayout.addWidget(self.helpLabel, 0, Qt.AlignCenter)
|
||||
|
||||
self.setLayout(self.mainLayout)
|
||||
|
||||
return
|
||||
@@ -0,0 +1,9 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
__ALL__ = ['bootstrap','${NameLower}_dialog']
|
||||
@@ -0,0 +1,117 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
# -------------------------------------------------------------------------
|
||||
"""${SanitizedCppName}\\editor\\scripts\\boostrap.py
|
||||
Generated from O3DE PythonGem Template"""
|
||||
|
||||
import azlmbr
|
||||
import az_qt_helpers
|
||||
from PySide2 import QtCore, QtWidgets, QtGui
|
||||
from PySide2.QtCore import QEvent, Qt
|
||||
from PySide2.QtWidgets import QMainWindow, QAction, QDialog, QHeaderView, QLabel, QLineEdit, QPushButton, QSplitter, QTreeWidget, QTreeWidgetItem, QWidget, QAbstractButton
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
class SampleUI(QtWidgets.QDialog):
|
||||
"""Lightweight UI Test Class created a button"""
|
||||
def __init__(self, parent, title='Not Set'):
|
||||
super(SampleUI, self).__init__(parent)
|
||||
self.setWindowTitle(title)
|
||||
self.initUI()
|
||||
|
||||
def initUI(self):
|
||||
mainLayout = QtWidgets.QHBoxLayout()
|
||||
testBtn = QtWidgets.QPushButton("I am just a Button man!")
|
||||
mainLayout.addWidget(testBtn)
|
||||
self.setLayout(mainLayout)
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("${SanitizedCppName}.boostrap, Generated from O3DE PythonGem Template")
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# validate pyside before continuing
|
||||
try:
|
||||
azlmbr.qt.QtForPythonRequestBus(azlmbr.bus.Broadcast, 'IsActive')
|
||||
params = azlmbr.qt.QtForPythonRequestBus(azlmbr.bus.Broadcast, 'GetQtBootstrapParameters')
|
||||
params is not None and params.mainWindowId is not 0
|
||||
from PySide2 import QtWidgets
|
||||
except Exception as e:
|
||||
_LOGGER.error(f'Pyside not available, exception: {e}')
|
||||
raise e
|
||||
|
||||
# keep going, import the other PySide2 bits we will use
|
||||
from PySide2 import QtGui
|
||||
from PySide2.QtCore import Slot
|
||||
from shiboken2 import wrapInstance, getCppPointer
|
||||
|
||||
# Get our Editor main window
|
||||
_widget_main_window = None
|
||||
try:
|
||||
_widget_main_window = az_qt_helpers.get_editor_main_window()
|
||||
except:
|
||||
pass # may be booting in the AP?
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
if _widget_main_window:
|
||||
# creat a custom menu
|
||||
_tag_str = '${SanitizedCppName}'
|
||||
|
||||
# create our own menuBar
|
||||
${SanitizedCppName}_menu = _widget_main_window.menuBar().addMenu(f"&{_tag_str}")
|
||||
|
||||
# nest a menu for util/tool launching
|
||||
${SanitizedCppName}_launch_menu = ${SanitizedCppName}_menu.addMenu("examples")
|
||||
else:
|
||||
print('No O3DE MainWindow')
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
if _widget_main_window:
|
||||
# (1) add the first SampleUI
|
||||
action_launch_sample_ui = ${SanitizedCppName}_launch_menu.addAction("O3DE:SampleUI")
|
||||
|
||||
@Slot()
|
||||
def clicked_sample_ui():
|
||||
while 1: # simple PySide2 test, set to 0 to disable
|
||||
ui = SampleUI(parent=_widget_main_window, title='O3DE:SampleUI')
|
||||
ui.show()
|
||||
break
|
||||
return
|
||||
# Add click event to menu bar
|
||||
action_launch_sample_ui.triggered.connect(clicked_sample_ui)
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
if _widget_main_window:
|
||||
# (1) and custom external module Qwidget
|
||||
action_launch_${SanitizedCppName}_dialog = ${SanitizedCppName}_launch_menu.addAction("O3DE:${SanitizedCppName}_dialog")
|
||||
|
||||
@Slot()
|
||||
def clicked_${SanitizedCppName}_dialog():
|
||||
while 1: # simple PySide2 test, set to 0 to disable
|
||||
try:
|
||||
import az_qt_helpers
|
||||
from ${NameLower}_dialog import ${SanitizedCppName}Dialog
|
||||
az_qt_helpers.register_view_pane('${SanitizedCppName} Popup', ${SanitizedCppName}Dialog)
|
||||
except Exception as e:
|
||||
print(f'Error: {e}')
|
||||
print('Skipping register our ${SanitizedCppName}Dialog with the Editor.')
|
||||
${SanitizedCppName}_dialog = ${SanitizedCppName}Dialog(parent=_widget_main_window)
|
||||
${SanitizedCppName}_dialog.show()
|
||||
break
|
||||
return
|
||||
# Add click event to menu bar
|
||||
action_launch_${SanitizedCppName}_dialog.triggered.connect(clicked_${SanitizedCppName}_dialog)
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
# end
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"gem_name": "${Name}",
|
||||
"display_name": "${Name}",
|
||||
"license": "What license ${Name} uses goes here: i.e. https://opensource.org/licenses/MIT",
|
||||
"origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com",
|
||||
"type": "Code",
|
||||
"summary": "A short description of ${Name}.",
|
||||
"canonical_tags": [
|
||||
"Gem"
|
||||
],
|
||||
"user_tags": [
|
||||
"${Name}"
|
||||
],
|
||||
"icon_path": "preview.png",
|
||||
"requirements": ""
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7ac9dd09bde78f389e3725ac49d61eff109857e004840bc0bc3881739df9618d
|
||||
size 2217
|
||||
@@ -0,0 +1,216 @@
|
||||
{
|
||||
"template_name": "PythonGem",
|
||||
"restricted_name": "o3de",
|
||||
"restricted_platform_relative_path": "Templates",
|
||||
"origin": "The primary repo for PythonGem goes here: i.e. http://www.mydomain.com",
|
||||
"license": "What license PythonGem uses goes here: i.e. https://opensource.org/licenses/MIT",
|
||||
"display_name": "PythonGem",
|
||||
"summary": "A short description of PythonGem.",
|
||||
"canonical_tags": [],
|
||||
"user_tags": [
|
||||
"PythonGem"
|
||||
],
|
||||
"icon_path": "preview.png",
|
||||
"copyFiles": [
|
||||
{
|
||||
"file": "CMakeLists.txt",
|
||||
"origin": "CMakeLists.txt",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/${NameLower}_editor_files.cmake",
|
||||
"origin": "Code/${NameLower}_editor_files.cmake",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/${NameLower}_editor_shared_files.cmake",
|
||||
"origin": "Code/${NameLower}_editor_shared_files.cmake",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/${NameLower}_editor_tests_files.cmake",
|
||||
"origin": "Code/${NameLower}_editor_tests_files.cmake",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/CMakeLists.txt",
|
||||
"origin": "Code/CMakeLists.txt",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Include/${Name}/${Name}Bus.h",
|
||||
"origin": "Code/Include/${Name}/${Name}Bus.h",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Platform/Linux/${NameLower}_linux_files.cmake",
|
||||
"origin": "Code/Platform/Linux/${NameLower}_linux_files.cmake",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake",
|
||||
"origin": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Platform/Linux/PAL_linux.cmake",
|
||||
"origin": "Code/Platform/Linux/PAL_linux.cmake",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Platform/Mac/${NameLower}_mac_files.cmake",
|
||||
"origin": "Code/Platform/Mac/${NameLower}_mac_files.cmake",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake",
|
||||
"origin": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Platform/Mac/PAL_mac.cmake",
|
||||
"origin": "Code/Platform/Mac/PAL_mac.cmake",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake",
|
||||
"origin": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Platform/Windows/${NameLower}_windows_files.cmake",
|
||||
"origin": "Code/Platform/Windows/${NameLower}_windows_files.cmake",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Platform/Windows/PAL_windows.cmake",
|
||||
"origin": "Code/Platform/Windows/PAL_windows.cmake",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Source/${Name}EditorModule.cpp",
|
||||
"origin": "Code/Source/${Name}EditorModule.cpp",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Source/${Name}EditorSystemComponent.cpp",
|
||||
"origin": "Code/Source/${Name}EditorSystemComponent.cpp",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Source/${Name}EditorSystemComponent.h",
|
||||
"origin": "Code/Source/${Name}EditorSystemComponent.h",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Source/${Name}ModuleInterface.h",
|
||||
"origin": "Code/Source/${Name}ModuleInterface.h",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Code/Tests/${Name}EditorTest.cpp",
|
||||
"origin": "Code/Tests/${Name}EditorTest.cpp",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Editor/Scripts/__init__.py",
|
||||
"origin": "Editor/Scripts/__init__.py",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Editor/Scripts/bootstrap.py",
|
||||
"origin": "Editor/Scripts/bootstrap.py",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "Editor/Scripts/${NameLower}_dialog.py",
|
||||
"origin": "Editor/Scripts/${NameLower}_dialog.py",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "gem.json",
|
||||
"origin": "gem.json",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
},
|
||||
{
|
||||
"file": "preview.png",
|
||||
"origin": "preview.png",
|
||||
"isTemplated": false,
|
||||
"isOptional": false
|
||||
}
|
||||
],
|
||||
"createDirectories": [
|
||||
{
|
||||
"dir": "Assets",
|
||||
"origin": "Assets"
|
||||
},
|
||||
{
|
||||
"dir": "Code",
|
||||
"origin": "Code"
|
||||
},
|
||||
{
|
||||
"dir": "Editor",
|
||||
"origin": "Editor"
|
||||
},
|
||||
{
|
||||
"dir": "Editor/Scripts",
|
||||
"origin": "Editor/Scripts"
|
||||
},
|
||||
{
|
||||
"dir": "Code/Include",
|
||||
"origin": "Code/Include"
|
||||
},
|
||||
{
|
||||
"dir": "Code/Include/${Name}",
|
||||
"origin": "Code/Include/${Name}"
|
||||
},
|
||||
{
|
||||
"dir": "Code/Platform",
|
||||
"origin": "Code/Platform"
|
||||
},
|
||||
{
|
||||
"dir": "Code/Platform/Linux",
|
||||
"origin": "Code/Platform/Linux"
|
||||
},
|
||||
{
|
||||
"dir": "Code/Platform/Mac",
|
||||
"origin": "Code/Platform/Mac"
|
||||
},
|
||||
{
|
||||
"dir": "Code/Platform/Windows",
|
||||
"origin": "Code/Platform/Windows"
|
||||
},
|
||||
{
|
||||
"dir": "Code/Source",
|
||||
"origin": "Code/Source"
|
||||
},
|
||||
{
|
||||
"dir": "Code/Tests",
|
||||
"origin": "Code/Tests"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+36
@@ -102,6 +102,10 @@ def IsJobEnabled(branchName, buildTypeMap, pipelineName, platformName) {
|
||||
}
|
||||
}
|
||||
|
||||
def IsAPLogUpload(branchName, jobName) {
|
||||
return !IsPullRequest(branchName) && jobName.toLowerCase().contains('asset') && env.AP_LOGS_S3_BUCKET
|
||||
}
|
||||
|
||||
def GetRunningPipelineName(JENKINS_JOB_NAME) {
|
||||
// If the job name has an underscore
|
||||
def job_parts = JENKINS_JOB_NAME.tokenize('/')[0].tokenize('_')
|
||||
@@ -431,6 +435,27 @@ def ExportTestScreenshots(Map options, String branchName, String platformName, S
|
||||
}
|
||||
}
|
||||
|
||||
def UploadAPLogs(Map options, String branchName, String jobName, String workspace, Map params) {
|
||||
dir("${workspace}/${ENGINE_REPOSITORY_NAME}") {
|
||||
projects = params.CMAKE_LY_PROJECTS.split(",")
|
||||
projects.each{ project ->
|
||||
def apLogsPath = "${project}/user/log"
|
||||
def s3UploadScriptPath = "scripts/build/tools/upload_to_s3.py"
|
||||
if(env.IS_UNIX) {
|
||||
pythonPath = "${options.PYTHON_DIR}/python.sh"
|
||||
}
|
||||
else {
|
||||
pythonPath = "${options.PYTHON_DIR}/python.cmd"
|
||||
}
|
||||
def command = "${pythonPath} -u ${s3UploadScriptPath} --base_dir ${apLogsPath} " +
|
||||
"--file_regex \".*\" --bucket ${env.AP_LOGS_S3_BUCKET} " +
|
||||
"--search_subdirectories True --key_prefix ${env.JOB_NAME}/${branchName}/${env.BUILD_NUMBER}/${jobName}" +
|
||||
"--extra-args {\"ACL\": \"bucket-owner-full-control\"}"
|
||||
palSh(command, "Uploading AP logs for job ${jobName} for branch ${branchName}", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def PostBuildCommonSteps(String workspace, boolean mount = true) {
|
||||
echo 'Starting post-build common steps...'
|
||||
|
||||
@@ -494,6 +519,14 @@ def CreateExportTestScreenshotsStage(Map pipelineConfig, String branchName, Stri
|
||||
}
|
||||
}
|
||||
|
||||
def CreateUploadAPLogsStage(Map pipelineConfig, String branchName, String jobName, String workspace, Map params) {
|
||||
return {
|
||||
stage("${jobName}_upload_ap_logs") {
|
||||
UploadAPLogs(pipelineConfig, branchName, jobName, workspace, params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def CreateTeardownStage(Map environmentVars) {
|
||||
return {
|
||||
stage('Teardown') {
|
||||
@@ -543,6 +576,9 @@ def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVar
|
||||
error "Node disconnected during build: ${e}" // Error raised to retry stage on a new node
|
||||
}
|
||||
}
|
||||
if (IsAPLogUpload(branchName, build_job_name)) {
|
||||
CreateUploadAPLogsStage(pipelineConfig, branchName, build_job_name, envVars['WORKSPACE'], platform.value.build_types[build_job_name].PARAMETERS).call()
|
||||
}
|
||||
// All other errors will be raised outside the retry block
|
||||
currentResult = envVars['ON_FAILURE_MARK'] ?: 'FAILURE'
|
||||
currentException = e.toString()
|
||||
|
||||
@@ -12,7 +12,12 @@ libxcb-xinerama0 # For Qt plugins at runtime
|
||||
libxcb-xinput0 # For Qt plugins at runtime
|
||||
libfontconfig1-dev # For Qt plugins at runtime
|
||||
libcurl4-openssl-dev # For HttpRequestor
|
||||
libsdl2-dev # for WWise/Audio
|
||||
libsdl2-dev # For WWise/Audio
|
||||
libxcb-xkb-dev # For xcb keyboard input
|
||||
libxkbcommon-x11-dev # For xcb keyboard input
|
||||
libxkbcommon-dev # For xcb keyboard input
|
||||
libxcb-xfixes0-dev # For mouse input
|
||||
libxcb-xinput-dev # For mouse input
|
||||
zlib1g-dev
|
||||
mesa-common-dev
|
||||
|
||||
|
||||
@@ -16,5 +16,7 @@ libsdl2-dev # for WWise/Audio
|
||||
libxcb-xkb-dev # For xcb keyboard input
|
||||
libxkbcommon-x11-dev # For xcb keyboard input
|
||||
libxkbcommon-dev # For xcb keyboard input
|
||||
libxcb-xfixes0-dev # For mouse input
|
||||
libxcb-xinput-dev # For mouse input
|
||||
zlib1g-dev
|
||||
mesa-common-dev
|
||||
|
||||
Reference in New Issue
Block a user