Merge branch 'development' into Atom/guthadam/thumbnail_and_preview_refactor
This commit is contained in:
@@ -42,5 +42,8 @@ class TestAutomation(EditorTestSuite):
|
||||
class AtomEditorComponents_DisplayMapperAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_DisplayMapperAdded as test_module
|
||||
|
||||
class AtomEditorComponents_ReflectionProbeAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_ReflectionProbeAdded as test_module
|
||||
|
||||
class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest):
|
||||
from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module
|
||||
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
class Tests:
|
||||
creation_undo = (
|
||||
"UNDO Entity creation success",
|
||||
"UNDO Entity creation failed")
|
||||
creation_redo = (
|
||||
"REDO Entity creation success",
|
||||
"REDO Entity creation failed")
|
||||
reflection_probe_creation = (
|
||||
"Reflection Probe Entity successfully created",
|
||||
"Reflection Probe Entity failed to be created")
|
||||
reflection_probe_component = (
|
||||
"Entity has a Reflection Probe component",
|
||||
"Entity failed to find Reflection Probe component")
|
||||
reflection_probe_disabled = (
|
||||
"Reflection Probe component disabled",
|
||||
"Reflection Probe component was not disabled.")
|
||||
reflection_map_generated = (
|
||||
"Reflection Probe cubemap generated",
|
||||
"Reflection Probe cubemap not generated")
|
||||
box_shape_component = (
|
||||
"Entity has a Box Shape component",
|
||||
"Entity did not have a Box Shape component")
|
||||
reflection_probe_enabled = (
|
||||
"Reflection Probe component enabled",
|
||||
"Reflection Probe component was not enabled.")
|
||||
enter_game_mode = (
|
||||
"Entered game mode",
|
||||
"Failed to enter game mode")
|
||||
exit_game_mode = (
|
||||
"Exited game mode",
|
||||
"Couldn't exit game mode")
|
||||
is_visible = (
|
||||
"Entity is visible",
|
||||
"Entity was not visible")
|
||||
is_hidden = (
|
||||
"Entity is hidden",
|
||||
"Entity was not hidden")
|
||||
entity_deleted = (
|
||||
"Entity deleted",
|
||||
"Entity was not deleted")
|
||||
deletion_undo = (
|
||||
"UNDO deletion success",
|
||||
"UNDO deletion failed")
|
||||
deletion_redo = (
|
||||
"REDO deletion success",
|
||||
"REDO deletion failed")
|
||||
|
||||
|
||||
def AtomEditorComponents_ReflectionProbe_AddedToEntity():
|
||||
"""
|
||||
Summary:
|
||||
Tests the Reflection Probe component can be added to an entity and has the expected functionality.
|
||||
|
||||
Test setup:
|
||||
- Wait for Editor idle loop.
|
||||
- Open the "Base" level.
|
||||
|
||||
Expected Behavior:
|
||||
The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
|
||||
Creation and deletion undo/redo should also work.
|
||||
|
||||
Test Steps:
|
||||
1) Create a Reflection Probe entity with no components.
|
||||
2) Add a Reflection Probe component to Reflection Probe entity.
|
||||
3) UNDO the entity creation and component addition.
|
||||
4) REDO the entity creation and component addition.
|
||||
5) Verify Reflection Probe component not enabled.
|
||||
6) Add Shape component since it is required by the Reflection Probe component.
|
||||
7) Verify Reflection Probe component is enabled.
|
||||
8) Enter/Exit game mode.
|
||||
9) Test IsHidden.
|
||||
10) Test IsVisible.
|
||||
11) Verify cubemap generation
|
||||
12) Delete Reflection Probe entity.
|
||||
13) UNDO deletion.
|
||||
14) REDO deletion.
|
||||
15) Look for errors.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.render as render
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper
|
||||
|
||||
with Tracer() as error_tracer:
|
||||
# Test setup begins.
|
||||
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
|
||||
helper.init_idle()
|
||||
helper.open_level("", "Base")
|
||||
|
||||
# Test steps begin.
|
||||
# 1. Create a Reflection Probe entity with no components.
|
||||
reflection_probe_name = "Reflection Probe"
|
||||
reflection_probe_entity = EditorEntity.create_editor_entity_at(
|
||||
math.Vector3(512.0, 512.0, 34.0), reflection_probe_name)
|
||||
Report.critical_result(Tests.reflection_probe_creation, reflection_probe_entity.exists())
|
||||
|
||||
# 2. Add a Reflection Probe component to Reflection Probe entity.
|
||||
reflection_probe_component = reflection_probe_entity.add_component(reflection_probe_name)
|
||||
Report.critical_result(
|
||||
Tests.reflection_probe_component,
|
||||
reflection_probe_entity.has_component(reflection_probe_name))
|
||||
|
||||
# 3. UNDO the entity creation and component addition.
|
||||
# -> UNDO component addition.
|
||||
general.undo()
|
||||
# -> UNDO naming entity.
|
||||
general.undo()
|
||||
# -> UNDO selecting entity.
|
||||
general.undo()
|
||||
# -> UNDO entity creation.
|
||||
general.undo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_undo, not reflection_probe_entity.exists())
|
||||
|
||||
# 4. REDO the entity creation and component addition.
|
||||
# -> REDO entity creation.
|
||||
general.redo()
|
||||
# -> REDO selecting entity.
|
||||
general.redo()
|
||||
# -> REDO naming entity.
|
||||
general.redo()
|
||||
# -> REDO component addition.
|
||||
general.redo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_redo, reflection_probe_entity.exists())
|
||||
|
||||
# 5. Verify Reflection Probe component not enabled.
|
||||
Report.result(Tests.reflection_probe_disabled, not reflection_probe_component.is_enabled())
|
||||
|
||||
# 6. Add Box Shape component since it is required by the Reflection Probe component.
|
||||
box_shape = "Box Shape"
|
||||
reflection_probe_entity.add_component(box_shape)
|
||||
Report.result(Tests.box_shape_component, reflection_probe_entity.has_component(box_shape))
|
||||
|
||||
# 7. Verify Reflection Probe component is enabled.
|
||||
Report.result(Tests.reflection_probe_enabled, reflection_probe_component.is_enabled())
|
||||
|
||||
# 8. Enter/Exit game mode.
|
||||
helper.enter_game_mode(Tests.enter_game_mode)
|
||||
general.idle_wait_frames(1)
|
||||
helper.exit_game_mode(Tests.exit_game_mode)
|
||||
|
||||
# 9. Test IsHidden.
|
||||
reflection_probe_entity.set_visibility_state(False)
|
||||
Report.result(Tests.is_hidden, reflection_probe_entity.is_hidden() is True)
|
||||
|
||||
# 10. Test IsVisible.
|
||||
reflection_probe_entity.set_visibility_state(True)
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.is_visible, reflection_probe_entity.is_visible() is True)
|
||||
|
||||
# 11. Verify cubemap generation
|
||||
render.EditorReflectionProbeBus(azlmbr.bus.Event, "BakeReflectionProbe", reflection_probe_entity.id)
|
||||
Report.result(
|
||||
Tests.reflection_map_generated,
|
||||
helper.wait_for_condition(
|
||||
lambda: reflection_probe_component.get_component_property_value("Cubemap|Baked Cubemap Path") != "",
|
||||
20.0))
|
||||
|
||||
# 12. Delete Reflection Probe entity.
|
||||
reflection_probe_entity.delete()
|
||||
Report.result(Tests.entity_deleted, not reflection_probe_entity.exists())
|
||||
|
||||
# 13. UNDO deletion.
|
||||
general.undo()
|
||||
Report.result(Tests.deletion_undo, reflection_probe_entity.exists())
|
||||
|
||||
# 14. REDO deletion.
|
||||
general.redo()
|
||||
Report.result(Tests.deletion_redo, not reflection_probe_entity.exists())
|
||||
|
||||
# 15. Look for errors or asserts.
|
||||
helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
|
||||
for error_info in error_tracer.errors:
|
||||
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
|
||||
for assert_info in error_tracer.asserts:
|
||||
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(AtomEditorComponents_ReflectionProbe_AddedToEntity)
|
||||
@@ -18,6 +18,14 @@
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
|
||||
#include <AzCore/Threading/ThreadUtils.h>
|
||||
|
||||
AZ_CVAR(float, cl_jobThreadsConcurrencyRatio, 0.6f, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system multiplier on the number of hw threads the machine creates at initialization");
|
||||
AZ_CVAR(uint32_t, cl_jobThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system number of hardware threads that are reserved for O3DE system threads");
|
||||
AZ_CVAR(uint32_t, cl_jobThreadsMinNumber, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system minimum number of worker threads to create after scaling the number of hw threads");
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
//=========================================================================
|
||||
@@ -46,9 +54,10 @@ namespace AZ
|
||||
JobManagerThreadDesc threadDesc;
|
||||
|
||||
int numberOfWorkerThreads = m_numberOfWorkerThreads;
|
||||
if (numberOfWorkerThreads <= 0)
|
||||
if (numberOfWorkerThreads <= 0) // spawn default number of threads
|
||||
{
|
||||
numberOfWorkerThreads = AZ::GetMin(static_cast<unsigned int>(desc.m_workerThreads.capacity()), AZStd::thread::hardware_concurrency());
|
||||
uint32_t scaledHardwareThreads = Threading::CalcNumWorkerThreads(cl_jobThreadsConcurrencyRatio, cl_jobThreadsMinNumber, cl_jobThreadsNumReserved);
|
||||
numberOfWorkerThreads = AZ::GetMin(static_cast<unsigned int>(desc.m_workerThreads.capacity()), scaledHardwareThreads);
|
||||
#if (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS)
|
||||
numberOfWorkerThreads = AZ::GetMin(numberOfWorkerThreads, AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS);
|
||||
#endif // (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS)
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace AZ
|
||||
*/
|
||||
int m_stackSize;
|
||||
|
||||
JobManagerThreadDesc(int cpuId = -1, int priority = -100000, int stackSize = -1)
|
||||
JobManagerThreadDesc(int cpuId = -1, int priority = 0, int stackSize = -1)
|
||||
: m_cpuId(cpuId)
|
||||
, m_priority(priority)
|
||||
, m_stackSize(stackSize)
|
||||
|
||||
@@ -308,11 +308,11 @@ namespace AZ
|
||||
|
||||
void TaskExecutor::SetInstance(TaskExecutor* executor)
|
||||
{
|
||||
if (!executor)
|
||||
if (!executor) // allow unsetting the executor
|
||||
{
|
||||
s_executor.Reset();
|
||||
}
|
||||
else if (!s_executor) // ignore any calls to set after the first (this happens in unit tests that create new system entities)
|
||||
else if (!s_executor) // ignore any extra executors after the first (this happens during unit tests)
|
||||
{
|
||||
s_executor = AZ::Environment::CreateVariable<TaskExecutor*>(s_executorName, executor);
|
||||
}
|
||||
|
||||
@@ -11,9 +11,15 @@
|
||||
#include <AzCore/Task/TaskGraphSystemComponent.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
#include <AzCore/Threading/ThreadUtils.h>
|
||||
|
||||
// Create a cvar as a central location for experimentation with switching from the Job system to TaskGraph system.
|
||||
AZ_CVAR(bool, cl_activateTaskGraph, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Flag clients of TaskGraph to switch between jobs/taskgraph (Note does not disable task graph system)");
|
||||
AZ_CVAR(float, cl_taskGraphThreadsConcurrencyRatio, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph calculate the number of worker threads to spawn by scaling the number of hw threads, value is clamped between 0.0f and 1.0f");
|
||||
AZ_CVAR(uint32_t, cl_taskGraphThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph number of hardware threads that are reserved for O3DE system threads. Value is clamped between 0 and the number of logical cores in the system");
|
||||
AZ_CVAR(uint32_t, cl_taskGraphThreadsMinNumber, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph minimum number of worker threads to create after scaling the number of hw threads");
|
||||
|
||||
static constexpr uint32_t TaskExecutorServiceCrc = AZ_CRC_CE("TaskExecutorService");
|
||||
|
||||
namespace AZ
|
||||
@@ -24,8 +30,8 @@ namespace AZ
|
||||
|
||||
if (Interface<TaskGraphActiveInterface>::Get() == nullptr)
|
||||
{
|
||||
Interface<TaskGraphActiveInterface>::Register(this);
|
||||
m_taskExecutor = aznew TaskExecutor();
|
||||
Interface<TaskGraphActiveInterface>::Register(this); // small window that another thread can try to use taskgraph between this line and the set instance.
|
||||
m_taskExecutor = aznew TaskExecutor(Threading::CalcNumWorkerThreads(cl_taskGraphThreadsConcurrencyRatio, cl_taskGraphThreadsMinNumber, cl_taskGraphThreadsNumReserved));
|
||||
TaskExecutor::SetInstance(m_taskExecutor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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/Threading/ThreadUtils.h>
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
|
||||
namespace AZ::Threading
|
||||
{
|
||||
uint32_t CalcNumWorkerThreads(float workerThreadsRatio, uint32_t minNumWorkerThreads, uint32_t reservedNumThreads)
|
||||
{
|
||||
const uint32_t maxHardwareThreads = AZStd::thread::hardware_concurrency();
|
||||
const uint32_t numReservedThreads = AZ::GetMin<uint32_t>(reservedNumThreads, maxHardwareThreads); // protect against num reserved being bigger than the number of hw threads
|
||||
const uint32_t maxWorkerThreads = maxHardwareThreads - numReservedThreads;
|
||||
const float requestedWorkerThreads = AZ::GetClamp<float>(workerThreadsRatio, 0.0f, 1.0f) * static_cast<float>(maxWorkerThreads);
|
||||
const uint32_t requestedWorkerThreadsRounded = AZStd::lround(requestedWorkerThreads);
|
||||
const uint32_t numWorkerThreads = AZ::GetMax<uint32_t>(minNumWorkerThreads, requestedWorkerThreadsRounded);
|
||||
return numWorkerThreads;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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/base.h>
|
||||
|
||||
namespace AZ::Threading
|
||||
{
|
||||
//! Calculates the number of worker threads a system should use based on the number of hardware threads a device has.
|
||||
//! result = max (minNumWorkerThreads, workerThreadsRatio * (num_hardware_threads - reservedNumThreads))
|
||||
//! @param workerThreadsRatio scale applied to the calculated maximum number of threads available after reserved threads have been accounted for. Clamped between 0 and 1.
|
||||
//! @param minNumWorkerThreads minimum value that will be returned. Value is unclamped and can be more than num_hardware_threads.
|
||||
//! @param reservedNumThreads number of hardware threads to reserve for O3DE system threads. Value clamped to num_hardware_threads.
|
||||
//! @return number of worker threads for the calling system to allocate
|
||||
uint32_t CalcNumWorkerThreads(float workerThreadsRatio, uint32_t minNumWorkerThreads, uint32_t reservedNumThreads);
|
||||
};
|
||||
@@ -639,6 +639,8 @@ set(FILES
|
||||
Threading/ThreadSafeDeque.inl
|
||||
Threading/ThreadSafeObject.h
|
||||
Threading/ThreadSafeObject.inl
|
||||
Threading/ThreadUtils.h
|
||||
Threading/ThreadUtils.cpp
|
||||
Time/ITime.h
|
||||
Time/TimeSystemComponent.cpp
|
||||
Time/TimeSystemComponent.h
|
||||
|
||||
+4
@@ -59,6 +59,10 @@ namespace AZStd
|
||||
{
|
||||
priority = desc->m_priority;
|
||||
}
|
||||
else
|
||||
{
|
||||
priority = SCHED_OTHER;
|
||||
}
|
||||
if (desc->m_name)
|
||||
{
|
||||
name = desc->m_name;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace UnitTest
|
||||
R"X(Executing RC.EXE: '"E:\lyengine\dev\windows\bin\profile\rc.exe" "E:/Directory/File.tga")X",
|
||||
R"X(Executing RC.EXE with working directory : '')X",
|
||||
R"X(ResourceCompiler 64 - bit DEBUG)X",
|
||||
R"X(Platform support : PC, PowerVR, etc2Comp)X",
|
||||
R"X(Platform support : PC, PowerVR)X",
|
||||
R"X(Version 1.1.8.6 Nov 5 2018 13 : 28 : 28)X"
|
||||
};
|
||||
|
||||
|
||||
@@ -74,7 +74,12 @@ namespace AWSMetrics
|
||||
{
|
||||
behaviorContext->EBus<AWSMetricsRequestBus>("AWSMetricsRequestBus", "Generate and submit metrics to the metrics analytics pipeline")
|
||||
->Attribute(AZ::Script::Attributes::Category, "AWSMetrics")
|
||||
->Event("SubmitMetrics", &AWSMetricsRequestBus::Events::SubmitMetrics)
|
||||
->Event(
|
||||
"SubmitMetrics", &AWSMetricsRequestBus::Events::SubmitMetrics,
|
||||
{ { { "Metrics Attributes list", "The list of metrics attributes to submit." },
|
||||
{ "Event priority", "Priority of the event. Defaults to 0, which is highest priority." },
|
||||
{ "Event source override", "Event source used to override the default, 'AWSMetricGem'." },
|
||||
{ "Buffer metrics", "Whether to buffer metrics and send them in a batch." } } })
|
||||
->Event("FlushMetrics", &AWSMetricsRequestBus::Events::FlushMetrics)
|
||||
;
|
||||
|
||||
|
||||
@@ -63,13 +63,10 @@ ly_add_target(
|
||||
3rdParty::Qt::Widgets
|
||||
3rdParty::Qt::Gui
|
||||
3rdParty::astc-encoder
|
||||
3rdParty::etc2comp
|
||||
3rdParty::PVRTexTool
|
||||
3rdParty::squish-ccr
|
||||
3rdParty::tiff
|
||||
3rdParty::ISPCTexComp
|
||||
3rdParty::ilmbase
|
||||
Legacy::CryCommon
|
||||
AZ::AzFramework
|
||||
AZ::AzToolsFramework
|
||||
AZ::AzQtComponents
|
||||
|
||||
+1
-11
@@ -39,16 +39,7 @@ namespace ImageProcessingAtom
|
||||
ePixelFormat_ASTC_10x8,
|
||||
ePixelFormat_ASTC_10x10,
|
||||
ePixelFormat_ASTC_12x10,
|
||||
ePixelFormat_ASTC_12x12,
|
||||
//Formats supported by PowerVR GPU. Mainly for ios devices.
|
||||
ePixelFormat_PVRTC2, //2bpp
|
||||
ePixelFormat_PVRTC4, //4bpp
|
||||
//formats for opengl and opengles 3.0 (android devices)
|
||||
ePixelFormat_EAC_R11, //one channel unsigned data
|
||||
ePixelFormat_EAC_RG11, //two channel unsigned data
|
||||
ePixelFormat_ETC2, //Compresses RGB888 data, it taks 4x4 groups of pixel data and compresses each into a 64-bit
|
||||
ePixelFormat_ETC2a1, //Compresses RGB888A1 data, it taks 4x4 groups of pixel data and compresses each into a 64-bit
|
||||
ePixelFormat_ETC2a, //Compresses RGBA8888 data with full alpha support
|
||||
ePixelFormat_ASTC_12x12,
|
||||
|
||||
// Standardized Compressed DXGI Formats (DX10+)
|
||||
// Data in these compressed formats is hardware decodable on all DX10 chips, and manageable with the DX10-API.
|
||||
@@ -88,7 +79,6 @@ namespace ImageProcessingAtom
|
||||
};
|
||||
|
||||
bool IsASTCFormat(EPixelFormat fmt);
|
||||
bool IsETCFormat(EPixelFormat fmt);
|
||||
} // namespace ImageProcessingAtom
|
||||
|
||||
namespace AZ
|
||||
|
||||
@@ -109,13 +109,6 @@ namespace ImageProcessingAtom
|
||||
->Value("ASTC_10x10", EPixelFormat::ePixelFormat_ASTC_10x10)
|
||||
->Value("ASTC_12x10", EPixelFormat::ePixelFormat_ASTC_12x10)
|
||||
->Value("ASTC_12x12", EPixelFormat::ePixelFormat_ASTC_12x12)
|
||||
->Value("PVRTC2", EPixelFormat::ePixelFormat_PVRTC2)
|
||||
->Value("PVRTC4", EPixelFormat::ePixelFormat_PVRTC4)
|
||||
->Value("EAC_R11", EPixelFormat::ePixelFormat_EAC_R11)
|
||||
->Value("EAC_RG11", EPixelFormat::ePixelFormat_EAC_RG11)
|
||||
->Value("ETC2", EPixelFormat::ePixelFormat_ETC2)
|
||||
->Value("ETC2a1", EPixelFormat::ePixelFormat_ETC2a1)
|
||||
->Value("ETC2a", EPixelFormat::ePixelFormat_ETC2a)
|
||||
->Value("BC1", EPixelFormat::ePixelFormat_BC1)
|
||||
->Value("BC1a", EPixelFormat::ePixelFormat_BC1a)
|
||||
->Value("BC3", EPixelFormat::ePixelFormat_BC3)
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
#include <Compressors/ASTCCompressor.h>
|
||||
#include <Compressors/CTSquisher.h>
|
||||
#include <Compressors/PVRTC.h>
|
||||
#include <Compressors/ETC2.h>
|
||||
#include <Compressors/ISPCTextureCompressor.h>
|
||||
|
||||
namespace ImageProcessingAtom
|
||||
@@ -42,26 +40,6 @@ namespace ImageProcessingAtom
|
||||
}
|
||||
}
|
||||
|
||||
// Both ETC2Compressor and PVRTCCompressor can process ETC formats
|
||||
// According to Mobile team, Etc2Com is faster than PVRTexLib, so we check with ETC2Compressor before PVRTCCompressor
|
||||
// Note: with the test I have done, I found out it cost similar time for both Etc2Com and PVRTexLib to compress
|
||||
// a 2048x2048 test texture to EAC_R11 and EAC_RG11. It was around 7 minutes for EAC_R11 and 14 minutes for EAC_RG11
|
||||
if (ETC2Compressor::IsCompressedPixelFormatSupported(fmt))
|
||||
{
|
||||
if (isCompressing || (!isCompressing && ETC2Compressor::DoesSupportDecompress(fmt)))
|
||||
{
|
||||
return ICompressorPtr(new ETC2Compressor());
|
||||
}
|
||||
}
|
||||
|
||||
if (PVRTCCompressor::IsCompressedPixelFormatSupported(fmt))
|
||||
{
|
||||
if (isCompressing || (!isCompressing && PVRTCCompressor::DoesSupportDecompress(fmt)))
|
||||
{
|
||||
return ICompressorPtr(new PVRTCCompressor());
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,233 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <Atom/ImageProcessing/ImageObject.h>
|
||||
#include <Processing/PixelFormatInfo.h>
|
||||
#include <Processing/ImageFlags.h>
|
||||
#include <Converters/PixelOperation.h>
|
||||
#include <Compressors/ETC2.h>
|
||||
|
||||
#include <EtcConfig.h>
|
||||
#include <Etc.h>
|
||||
#include <EtcImage.h>
|
||||
#include <EtcColorFloatRGBA.h>
|
||||
|
||||
namespace ImageProcessingAtom
|
||||
{
|
||||
//limited to 1 thread because AP requires so. We may change to n when AP allocate n thread to a job in the furture
|
||||
static const int MAX_COMP_JOBS = 1;
|
||||
static const int MIN_COMP_JOBS = 1;
|
||||
static const float ETC_LOW_EFFORT_LEVEL = 25.0f;
|
||||
static const float ETC_MED_EFFORT_LEVEL = 40.0f;
|
||||
static const float ETC_HIGH_EFFORT_LEVEL = 80.0f;
|
||||
|
||||
//Grab the Etc2Comp specific pixel format enum
|
||||
static Etc::Image::Format FindEtc2PixelFormat(EPixelFormat fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case ePixelFormat_EAC_RG11:
|
||||
return Etc::Image::Format::RG11;
|
||||
case ePixelFormat_EAC_R11:
|
||||
return Etc::Image::Format::R11;
|
||||
case ePixelFormat_ETC2:
|
||||
return Etc::Image::Format::RGB8;
|
||||
case ePixelFormat_ETC2a1:
|
||||
return Etc::Image::Format::RGB8A1;
|
||||
case ePixelFormat_ETC2a:
|
||||
return Etc::Image::Format::RGBA8;
|
||||
default:
|
||||
return Etc::Image::Format::FORMATS;
|
||||
}
|
||||
}
|
||||
|
||||
//Get the errmetric required for the compression
|
||||
static Etc::ErrorMetric FindErrMetric(Etc::Image::Format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case Etc::Image::Format::RG11:
|
||||
return Etc::ErrorMetric::NORMALXYZ;
|
||||
case Etc::Image::Format::R11:
|
||||
return Etc::ErrorMetric::NUMERIC;
|
||||
case Etc::Image::Format::RGB8:
|
||||
return Etc::ErrorMetric::RGBX;
|
||||
case Etc::Image::Format::RGBA8:
|
||||
case Etc::Image::Format::RGB8A1:
|
||||
return Etc::ErrorMetric::RGBA;
|
||||
default:
|
||||
return Etc::ErrorMetric::ERROR_METRICS;
|
||||
}
|
||||
}
|
||||
|
||||
//Convert to sRGB format
|
||||
static Etc::Image::Format FindGammaEtc2PixelFormat(Etc::Image::Format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case Etc::Image::Format::RGB8:
|
||||
return Etc::Image::Format::SRGB8;
|
||||
case Etc::Image::Format::RGBA8:
|
||||
return Etc::Image::Format::SRGBA8;
|
||||
case Etc::Image::Format::RGB8A1:
|
||||
return Etc::Image::Format::SRGB8A1;
|
||||
default:
|
||||
return Etc::Image::Format::FORMATS;
|
||||
}
|
||||
}
|
||||
|
||||
bool ETC2Compressor::IsCompressedPixelFormatSupported(EPixelFormat fmt)
|
||||
{
|
||||
return (FindEtc2PixelFormat(fmt) != Etc::Image::Format::FORMATS);
|
||||
}
|
||||
|
||||
bool ETC2Compressor::IsUncompressedPixelFormatSupported(EPixelFormat fmt)
|
||||
{
|
||||
//for uncompress format
|
||||
if (fmt == ePixelFormat_R8G8B8A8)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
EPixelFormat ETC2Compressor::GetSuggestedUncompressedFormat([[maybe_unused]] EPixelFormat compressedfmt, [[maybe_unused]] EPixelFormat uncompressedfmt) const
|
||||
{
|
||||
return ePixelFormat_R8G8B8A8;
|
||||
}
|
||||
|
||||
bool ETC2Compressor::DoesSupportDecompress([[maybe_unused]] EPixelFormat fmtDst)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ColorSpace ETC2Compressor::GetSupportedColorSpace([[maybe_unused]] EPixelFormat compressFormat) const
|
||||
{
|
||||
return ColorSpace::autoSelect;
|
||||
}
|
||||
|
||||
const char* ETC2Compressor::GetName() const
|
||||
{
|
||||
return "ETC2Compressor";
|
||||
}
|
||||
|
||||
IImageObjectPtr ETC2Compressor::CompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst,
|
||||
const CompressOption* compressOption) const
|
||||
{
|
||||
//validate input
|
||||
EPixelFormat fmtSrc = srcImage->GetPixelFormat();
|
||||
|
||||
//src format need to be uncompressed and dst format need to compressed.
|
||||
if (!IsUncompressedPixelFormatSupported(fmtSrc) || !IsCompressedPixelFormatSupported(fmtDst))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IImageObjectPtr dstImage(srcImage->AllocateImage(fmtDst));
|
||||
|
||||
//determinate compression quality
|
||||
ICompressor::EQuality quality = ICompressor::eQuality_Normal;
|
||||
//get setting from compression option
|
||||
if (compressOption)
|
||||
{
|
||||
quality = compressOption->compressQuality;
|
||||
}
|
||||
|
||||
float qualityEffort = 0.0f;
|
||||
switch (quality)
|
||||
{
|
||||
case eQuality_Preview:
|
||||
case eQuality_Fast:
|
||||
{
|
||||
qualityEffort = ETC_LOW_EFFORT_LEVEL;
|
||||
break;
|
||||
}
|
||||
case eQuality_Normal:
|
||||
{
|
||||
qualityEffort = ETC_MED_EFFORT_LEVEL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
qualityEffort = ETC_HIGH_EFFORT_LEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
Etc::Image::Format dstEtc2Format = FindEtc2PixelFormat(fmtDst);
|
||||
if (srcImage->GetImageFlags() & EIF_SRGBRead)
|
||||
{
|
||||
dstEtc2Format = FindGammaEtc2PixelFormat(dstEtc2Format);
|
||||
}
|
||||
|
||||
//use to read pixel data from src image
|
||||
IPixelOperationPtr pixelOp = CreatePixelOperation(fmtSrc);
|
||||
//get count of bytes per pixel for images
|
||||
AZ::u32 pixelBytes = CPixelFormats::GetInstance().GetPixelFormatInfo(fmtSrc)->bitsPerBlock / 8;
|
||||
|
||||
const AZ::u32 mipCount = dstImage->GetMipCount();
|
||||
for (AZ::u32 mip = 0; mip < mipCount; ++mip)
|
||||
{
|
||||
const AZ::u32 width = srcImage->GetWidth(mip);
|
||||
const AZ::u32 height = srcImage->GetHeight(mip);
|
||||
|
||||
// Prepare source data
|
||||
AZ::u8* srcMem;
|
||||
AZ::u32 srcPitch;
|
||||
srcImage->GetImagePointer(mip, srcMem, srcPitch);
|
||||
const AZ::u32 pixelCount = srcImage->GetPixelCount(mip);
|
||||
|
||||
Etc::ColorFloatRGBA* rgbaPixels = new Etc::ColorFloatRGBA[pixelCount];
|
||||
Etc::ColorFloatRGBA* rgbaPixelPtr = rgbaPixels;
|
||||
float r, g, b, a;
|
||||
for (AZ::u32 pixelIdx = 0; pixelIdx < pixelCount; pixelIdx++, srcMem += pixelBytes, rgbaPixelPtr++)
|
||||
{
|
||||
pixelOp->GetRGBA(srcMem, r, g, b, a);
|
||||
rgbaPixelPtr->fA = a;
|
||||
rgbaPixelPtr->fR = r;
|
||||
rgbaPixelPtr->fG = g;
|
||||
rgbaPixelPtr->fB = b;
|
||||
}
|
||||
|
||||
//Call into etc2Comp lib to compress. https://medium.com/@duhroach/building-a-blazing-fast-etc2-compressor-307f3e9aad99
|
||||
Etc::ErrorMetric errMetric = FindErrMetric(dstEtc2Format);
|
||||
unsigned char* paucEncodingBits;
|
||||
unsigned int uiEncodingBitsBytes;
|
||||
unsigned int uiExtendedWidth;
|
||||
unsigned int uiExtendedHeight;
|
||||
int iEncodingTime_ms;
|
||||
|
||||
Etc::Encode(reinterpret_cast<float*>(rgbaPixels),
|
||||
width, height,
|
||||
dstEtc2Format,
|
||||
errMetric,
|
||||
qualityEffort,
|
||||
MIN_COMP_JOBS,
|
||||
MAX_COMP_JOBS,
|
||||
&paucEncodingBits, &uiEncodingBitsBytes,
|
||||
&uiExtendedWidth, &uiExtendedHeight,
|
||||
&iEncodingTime_ms);
|
||||
|
||||
AZ::u8* dstMem;
|
||||
AZ::u32 dstPitch;
|
||||
dstImage->GetImagePointer(mip, dstMem, dstPitch);
|
||||
|
||||
memcpy(dstMem, paucEncodingBits, uiEncodingBitsBytes);
|
||||
delete[] rgbaPixels;
|
||||
}
|
||||
|
||||
return dstImage;
|
||||
}
|
||||
|
||||
IImageObjectPtr ETC2Compressor::DecompressImage(IImageObjectPtr srcImage, [[maybe_unused]] EPixelFormat fmtDst) const
|
||||
{
|
||||
//etc2Comp doesn't support decompression
|
||||
//Since PVRTexLib support ETC formats too. It may take over the decompression.
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace ImageProcessingAtom
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Compressors/Compressor.h>
|
||||
|
||||
namespace ImageProcessingAtom
|
||||
{
|
||||
class ETC2Compressor
|
||||
: public ICompressor
|
||||
{
|
||||
public:
|
||||
static bool IsCompressedPixelFormatSupported(EPixelFormat fmt);
|
||||
static bool IsUncompressedPixelFormatSupported(EPixelFormat fmt);
|
||||
static bool DoesSupportDecompress(EPixelFormat fmtDst);
|
||||
|
||||
IImageObjectPtr CompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst, const CompressOption* compressOption) const override;
|
||||
IImageObjectPtr DecompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst) const override;
|
||||
|
||||
EPixelFormat GetSuggestedUncompressedFormat(EPixelFormat compressedfmt, EPixelFormat uncompressedfmt) const override;
|
||||
ColorSpace GetSupportedColorSpace(EPixelFormat compressFormat) const final;
|
||||
const char* GetName() const final;
|
||||
|
||||
};
|
||||
} // namespace ImageProcessingAtom
|
||||
@@ -1,338 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ImageProcessing_Traits_Platform.h>
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
#include <Atom/ImageProcessing/ImageObject.h>
|
||||
#include <Processing/ImageFlags.h>
|
||||
#include <Processing/PixelFormatInfo.h>
|
||||
#include <Compressors/PVRTC.h>
|
||||
|
||||
#include <PVRTexture.h>
|
||||
#include <PVRTextureUtilities.h>
|
||||
|
||||
|
||||
namespace ImageProcessingAtom
|
||||
{
|
||||
// Note: PVRTexLib supports ETC formats, PVRTC formats and BC formats
|
||||
// We haven't tested the performace to compress BC formats compare to CTSquisher
|
||||
// For PVRTC formats, we only added PVRTC 1 support for now
|
||||
// The compression for ePVRTPF_EAC_R11 and ePVRTPF_EAC_RG11 are very slow. It takes 7 and 14 minutes for a 2048x2048 texture.
|
||||
EPVRTPixelFormat FindPvrPixelFormat(EPixelFormat fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case ePixelFormat_PVRTC2:
|
||||
return ePVRTPF_PVRTCI_2bpp_RGBA;
|
||||
case ePixelFormat_PVRTC4:
|
||||
return ePVRTPF_PVRTCI_4bpp_RGBA;
|
||||
case ePixelFormat_EAC_R11:
|
||||
return ePVRTPF_EAC_R11;
|
||||
case ePixelFormat_EAC_RG11:
|
||||
return ePVRTPF_EAC_RG11;
|
||||
case ePixelFormat_ETC2:
|
||||
return ePVRTPF_ETC2_RGB;
|
||||
case ePixelFormat_ETC2a1:
|
||||
return ePVRTPF_ETC2_RGB_A1;
|
||||
case ePixelFormat_ETC2a:
|
||||
return ePVRTPF_ETC2_RGBA;
|
||||
default:
|
||||
return ePVRTPF_NumCompressedPFs;
|
||||
}
|
||||
}
|
||||
|
||||
bool PVRTCCompressor::IsCompressedPixelFormatSupported(EPixelFormat fmt)
|
||||
{
|
||||
return (FindPvrPixelFormat(fmt) != ePVRTPF_NumCompressedPFs);
|
||||
}
|
||||
|
||||
bool PVRTCCompressor::IsUncompressedPixelFormatSupported(EPixelFormat fmt)
|
||||
{
|
||||
//for uncompress format
|
||||
if (fmt == ePixelFormat_R8G8B8A8)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
EPixelFormat PVRTCCompressor::GetSuggestedUncompressedFormat([[maybe_unused]] EPixelFormat compressedfmt, [[maybe_unused]] EPixelFormat uncompressedfmt) const
|
||||
{
|
||||
return ePixelFormat_R8G8B8A8;
|
||||
}
|
||||
|
||||
ColorSpace PVRTCCompressor::GetSupportedColorSpace([[maybe_unused]] EPixelFormat compressFormat) const
|
||||
{
|
||||
return ColorSpace::autoSelect;
|
||||
}
|
||||
|
||||
const char* PVRTCCompressor::GetName() const
|
||||
{
|
||||
return "PVRTCCompressor";
|
||||
}
|
||||
|
||||
bool PVRTCCompressor::DoesSupportDecompress([[maybe_unused]] EPixelFormat fmtDst)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
IImageObjectPtr PVRTCCompressor::CompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst,
|
||||
const CompressOption* compressOption) const
|
||||
{
|
||||
//validate input
|
||||
EPixelFormat fmtSrc = srcImage->GetPixelFormat();
|
||||
|
||||
//src format need to be uncompressed and dst format need to compressed.
|
||||
if (!IsUncompressedPixelFormatSupported(fmtSrc) || !IsCompressedPixelFormatSupported(fmtDst))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IImageObjectPtr dstImage(srcImage->AllocateImage(fmtDst));
|
||||
|
||||
//determinate compression quality
|
||||
pvrtexture::ECompressorQuality internalQuality = pvrtexture::eETCFast;
|
||||
ICompressor::EQuality quality = ICompressor::eQuality_Normal;
|
||||
AZ::Vector3 uniformWeights = AZ::Vector3(0.3333f, 0.3334f, 0.3333f);
|
||||
AZ::Vector3 weights = uniformWeights;
|
||||
bool isUniform = true;
|
||||
//get setting from compression option
|
||||
if (compressOption)
|
||||
{
|
||||
quality = compressOption->compressQuality;
|
||||
weights = compressOption->rgbWeight;
|
||||
isUniform = (weights == uniformWeights);
|
||||
}
|
||||
|
||||
if (IsETCFormat(fmtDst))
|
||||
{
|
||||
if ((quality <= eQuality_Normal) && isUniform)
|
||||
{
|
||||
internalQuality = pvrtexture::eETCFast;
|
||||
}
|
||||
else if (quality <= eQuality_Normal)
|
||||
{
|
||||
internalQuality = pvrtexture::eETCNormal;
|
||||
}
|
||||
else if (isUniform)
|
||||
{
|
||||
internalQuality = pvrtexture::eETCSlow;
|
||||
}
|
||||
else
|
||||
{
|
||||
internalQuality = pvrtexture::eETCSlow;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (quality == eQuality_Preview)
|
||||
{
|
||||
internalQuality = pvrtexture::ePVRTCFastest;
|
||||
}
|
||||
else if (quality == eQuality_Fast)
|
||||
{
|
||||
internalQuality = pvrtexture::ePVRTCFast;
|
||||
}
|
||||
else if (quality == eQuality_Normal)
|
||||
{
|
||||
internalQuality = pvrtexture::ePVRTCNormal;
|
||||
}
|
||||
else
|
||||
{
|
||||
internalQuality = pvrtexture::ePVRTCHigh;
|
||||
}
|
||||
}
|
||||
|
||||
// setup color space
|
||||
EPVRTColourSpace cspace = ePVRTCSpacelRGB;
|
||||
if (srcImage->GetImageFlags() & EIF_SRGBRead)
|
||||
{
|
||||
cspace = ePVRTCSpacesRGB;
|
||||
}
|
||||
|
||||
//setup src texture for compression
|
||||
const pvrtexture::PixelType srcPixelType('r', 'g', 'b', 'a', 8, 8, 8, 8);
|
||||
const AZ::u32 dstMips = dstImage->GetMipCount();
|
||||
for (AZ::u32 mip = 0; mip < dstMips; ++mip)
|
||||
{
|
||||
const AZ::u32 width = srcImage->GetWidth(mip);
|
||||
const AZ::u32 height = srcImage->GetHeight(mip);
|
||||
|
||||
// Prepare source data
|
||||
AZ::u8* srcMem;
|
||||
uint32 srcPitch;
|
||||
srcImage->GetImagePointer(mip, srcMem, srcPitch);
|
||||
|
||||
const pvrtexture::CPVRTextureHeader srcHeader(
|
||||
srcPixelType.PixelTypeID, // AZ::u64 u64PixelFormat,
|
||||
width, // uint32 u32Height=1,
|
||||
height, // uint32 u32Width=1,
|
||||
1, // uint32 u32Depth=1,
|
||||
1, // uint32 u32NumMipMaps=1,
|
||||
1, // uint32 u32NumArrayMembers=1,
|
||||
1, // uint32 u32NumFaces=1,
|
||||
cspace, // EPVRTColourSpace eColourSpace=ePVRTCSpacelRGB,
|
||||
ePVRTVarTypeUnsignedByteNorm, // EPVRTVariableType eChannelType=ePVRTVarTypeUnsignedByteNorm,
|
||||
false); // bool bPreMultiplied=false);
|
||||
|
||||
pvrtexture::CPVRTexture compressTexture(srcHeader, srcMem);
|
||||
|
||||
//compressing
|
||||
bool isSuccess = false;
|
||||
#if AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH
|
||||
try
|
||||
#endif // AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH
|
||||
{
|
||||
isSuccess = pvrtexture::Transcode(
|
||||
compressTexture,
|
||||
pvrtexture::PixelType(FindPvrPixelFormat(fmtDst)),
|
||||
ePVRTVarTypeUnsignedByteNorm,
|
||||
cspace,
|
||||
internalQuality);
|
||||
}
|
||||
#if AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH
|
||||
catch (...)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Unknown exception in PVRTexLib");
|
||||
return nullptr;
|
||||
}
|
||||
#endif // AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH
|
||||
|
||||
if (!isSuccess)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Failed to compress image with PVRTexLib.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Getting compressed data
|
||||
const void* const compressedData = compressTexture.getDataPtr();
|
||||
if (!compressedData)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Failed to obtain compressed image data by using PVRTexLib");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const AZ::u32 compressedDataSize = compressTexture.getDataSize();
|
||||
if (dstImage->GetMipBufSize(mip) != compressedDataSize)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Compressed image data size mismatch while using PVRTexLib");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//save compressed data to dst image
|
||||
AZ::u8* dstMem;
|
||||
AZ::u32 dstPitch;
|
||||
dstImage->GetImagePointer(mip, dstMem, dstPitch);
|
||||
memcpy(dstMem, compressedData, compressedDataSize);
|
||||
}
|
||||
|
||||
return dstImage;
|
||||
}
|
||||
|
||||
IImageObjectPtr PVRTCCompressor::DecompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst) const
|
||||
{
|
||||
//validate input
|
||||
EPixelFormat fmtSrc = srcImage->GetPixelFormat(); //compressed
|
||||
|
||||
if (!IsCompressedPixelFormatSupported(fmtSrc) || !IsUncompressedPixelFormatSupported(fmtDst))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EPVRTColourSpace colorSpace = ePVRTCSpacelRGB;
|
||||
if (srcImage->GetImageFlags() & EIF_SRGBRead)
|
||||
{
|
||||
colorSpace = ePVRTCSpacesRGB;
|
||||
}
|
||||
|
||||
IImageObjectPtr dstImage(srcImage->AllocateImage(fmtDst));
|
||||
|
||||
const AZ::u32 mipCount = dstImage->GetMipCount();
|
||||
for (AZ::u32 mip = 0; mip < mipCount; ++mip)
|
||||
{
|
||||
const AZ::u32 width = srcImage->GetWidth(mip);
|
||||
const AZ::u32 height = srcImage->GetHeight(mip);
|
||||
|
||||
// Preparing source compressed data
|
||||
const pvrtexture::CPVRTextureHeader compressedHeader(
|
||||
FindPvrPixelFormat(fmtSrc), // AZ::u64 u64PixelFormat,
|
||||
width, // uint32 u32Height=1,
|
||||
height, // uint32 u32Width=1,
|
||||
1, // uint32 u32Depth=1,
|
||||
1, // uint32 u32NumMipMaps=1,
|
||||
1, // uint32 u32NumArrayMembers=1,
|
||||
1, // uint32 u32NumFaces=1,
|
||||
colorSpace, // EPVRTColourSpace eColourSpace=ePVRTCSpacelRGB,
|
||||
ePVRTVarTypeUnsignedByteNorm, // EPVRTVariableType eChannelType=ePVRTVarTypeUnsignedByteNorm,
|
||||
false); // bool bPreMultiplied=false);
|
||||
|
||||
const AZ::u32 compressedDataSize = compressedHeader.getDataSize();
|
||||
if (srcImage->GetMipBufSize(mip) != compressedDataSize)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Decompressed image data size mismatch while using PVRTexLib");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AZ::u8* srcMem;
|
||||
AZ::u32 srcPitch;
|
||||
srcImage->GetImagePointer(mip, srcMem, srcPitch);
|
||||
pvrtexture::CPVRTexture cTexture(compressedHeader, srcMem);
|
||||
|
||||
// Decompress
|
||||
bool bOk = false;
|
||||
#if AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH
|
||||
try
|
||||
{
|
||||
#endif // AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH
|
||||
bOk = pvrtexture::Transcode(
|
||||
cTexture,
|
||||
pvrtexture::PVRStandard8PixelType,
|
||||
ePVRTVarTypeUnsignedByteNorm,
|
||||
colorSpace,
|
||||
pvrtexture::ePVRTCHigh);
|
||||
|
||||
#if AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Unknown exception in PVRTexLib when decompressing");
|
||||
return nullptr;
|
||||
}
|
||||
#endif // AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH
|
||||
|
||||
if (!bOk)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Failed to decompress an image by using PVRTexLib");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Getting decompressed data
|
||||
const void* const pDecompressedData = cTexture.getDataPtr();
|
||||
if (!pDecompressedData)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Failed to obtain decompressed image data by using PVRTexLib");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const AZ::u32 decompressedDataSize = cTexture.getDataSize();
|
||||
if (dstImage->GetMipBufSize(mip) != decompressedDataSize)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Decompressed image data size mismatch while using PVRTexLib");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//save decompressed image to dst image
|
||||
AZ::u8* dstMem;
|
||||
AZ::u32 dstPitch;
|
||||
dstImage->GetImagePointer(mip, dstMem, dstPitch);
|
||||
memcpy(dstMem, pDecompressedData, decompressedDataSize);
|
||||
}
|
||||
|
||||
return dstImage;
|
||||
}
|
||||
} //namespace ImageProcessingAtom
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Compressors/Compressor.h>
|
||||
|
||||
namespace ImageProcessingAtom
|
||||
{
|
||||
class PVRTCCompressor
|
||||
: public ICompressor
|
||||
{
|
||||
public:
|
||||
static bool IsCompressedPixelFormatSupported(EPixelFormat fmt);
|
||||
static bool IsUncompressedPixelFormatSupported(EPixelFormat fmt);
|
||||
static bool DoesSupportDecompress(EPixelFormat fmtDst);
|
||||
|
||||
IImageObjectPtr CompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst, const CompressOption* compressOption) const override;
|
||||
IImageObjectPtr DecompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst) const override;
|
||||
|
||||
EPixelFormat GetSuggestedUncompressedFormat(EPixelFormat compressedfmt, EPixelFormat uncompressedfmt) const override;
|
||||
ColorSpace GetSupportedColorSpace(EPixelFormat compressFormat) const final;
|
||||
const char* GetName() const final;
|
||||
};
|
||||
} // namespace ImageProcessingAtom
|
||||
@@ -82,7 +82,6 @@ namespace ImageProcessingAtomEditor
|
||||
presetInfoText += "\n";
|
||||
presetInfoText += QString("Suppress Engine Reduce: %1\n").arg(presetSettings->m_suppressEngineReduce ? "True" : "False");
|
||||
presetInfoText += QString("Discard Alpha: %1\n").arg(presetSettings->m_discardAlpha ? "True" : "False");
|
||||
presetInfoText += QString("Is Power Of 2: %1\n").arg(presetSettings->m_isPowerOf2 ? "True" : "False");
|
||||
presetInfoText += QString("Is Color Chart: %1\n").arg(presetSettings->m_isColorChart ? "True" : "False");
|
||||
presetInfoText += QString("High Pass Mip: %1\n").arg(presetSettings->m_highPassMip);
|
||||
presetInfoText += QString("Gloss From Normal: %1\n").arg(presetSettings->m_glossFromNormals);
|
||||
|
||||
@@ -24,201 +24,6 @@ namespace ImageProcessingAtom
|
||||
{
|
||||
namespace DdsLoader
|
||||
{
|
||||
IImageObject* CreateImageFromHeaderLegacy(DDS_HEADER_LEGACY& header, DDS_HEADER_DXT10& exthead)
|
||||
{
|
||||
EPixelFormat eFormat = ePixelFormat_Unknown;
|
||||
AZ::u32 dwWidth, dwMips, dwHeight;
|
||||
AZ::u32 imageFlags = header.dwReserved1;
|
||||
AZ::Color colMinARGB, colMaxARGB;
|
||||
|
||||
dwWidth = header.dwWidth;
|
||||
dwHeight = header.dwHeight;
|
||||
dwMips = 1;
|
||||
if (header.dwHeaderFlags & DDS_HEADER_FLAGS_MIPMAP)
|
||||
{
|
||||
dwMips = header.dwMipMapCount;
|
||||
}
|
||||
if ((header.dwSurfaceFlags & DDS_SURFACE_FLAGS_CUBEMAP) && (header.dwCubemapFlags & DDS_CUBEMAP_ALLFACES))
|
||||
{
|
||||
AZ_Assert(header.dwReserved1 & EIF_Cubemap, "Image flag should have cubemap flag");
|
||||
dwHeight *= 6;
|
||||
}
|
||||
|
||||
colMinARGB = AZ::Color(header.cMinColor[0], header.cMinColor[1], header.cMinColor[2], header.cMinColor[3]);
|
||||
colMaxARGB = AZ::Color(header.cMaxColor[0], header.cMaxColor[1], header.cMaxColor[2], header.cMaxColor[3]);
|
||||
|
||||
//get pixel format
|
||||
{
|
||||
// DX10 formats
|
||||
if (header.ddspf.dwFourCC == FOURCC_DX10)
|
||||
{
|
||||
AZ::u32 dxgiFormat = exthead.dxgiFormat;
|
||||
|
||||
//remove the SRGB from dxgi format and add sRGB to image flag
|
||||
if (dxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)
|
||||
{
|
||||
dxgiFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
else if (dxgiFormat == DXGI_FORMAT_BC1_UNORM_SRGB)
|
||||
{
|
||||
dxgiFormat = DXGI_FORMAT_BC1_UNORM;
|
||||
}
|
||||
else if (dxgiFormat == DXGI_FORMAT_BC2_UNORM_SRGB)
|
||||
{
|
||||
dxgiFormat = DXGI_FORMAT_BC2_UNORM;
|
||||
}
|
||||
else if (dxgiFormat == DXGI_FORMAT_BC3_UNORM_SRGB)
|
||||
{
|
||||
dxgiFormat = DXGI_FORMAT_BC3_UNORM;
|
||||
}
|
||||
else if (dxgiFormat == DXGI_FORMAT_BC7_UNORM_SRGB)
|
||||
{
|
||||
dxgiFormat = DXGI_FORMAT_BC7_UNORM;
|
||||
}
|
||||
|
||||
//add rgb flag if the dxgiformat was changed (which means it was sRGB format) above
|
||||
if (dxgiFormat != exthead.dxgiFormat)
|
||||
{
|
||||
AZ_Assert(imageFlags & EIF_SRGBRead, "Image flags should have SRGBRead flag");
|
||||
imageFlags |= EIF_SRGBRead;
|
||||
}
|
||||
|
||||
//check all the pixel formats and find matching one
|
||||
if (dxgiFormat != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < ePixelFormat_Count; i++)
|
||||
{
|
||||
const PixelFormatInfo* info = CPixelFormats::GetInstance().GetPixelFormatInfo((EPixelFormat)i);
|
||||
if (static_cast<AZ::u32>(info->d3d10Format) == dxgiFormat)
|
||||
{
|
||||
eFormat = (EPixelFormat)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ePixelFormat_Count)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Unhandled d3d10 format: %d", dxgiFormat);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//for non-dx10 formats, use fourCC to find out its pixel formats
|
||||
//go through all pixel formats and find a match with the fourcc
|
||||
for (AZ::u32 formatIdx = 0; formatIdx < ePixelFormat_Count; formatIdx++)
|
||||
{
|
||||
const PixelFormatInfo* info = CPixelFormats::GetInstance().GetPixelFormatInfo((EPixelFormat)formatIdx);
|
||||
if (header.ddspf.dwFourCC == info->fourCC)
|
||||
{
|
||||
eFormat = (EPixelFormat)formatIdx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//legacy formats. This section is only used for load dds files converted by RC.exe
|
||||
//our save to dds file function won't use any of these fourcc
|
||||
if (eFormat == ePixelFormat_Unknown)
|
||||
{
|
||||
if (header.ddspf.dwFourCC == FOURCC_DXT1)
|
||||
{
|
||||
eFormat = ePixelFormat_BC1;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == FOURCC_DXT5)
|
||||
{
|
||||
eFormat = ePixelFormat_BC3;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == FOURCC_3DCP)
|
||||
{
|
||||
eFormat = ePixelFormat_BC4;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == FOURCC_3DC)
|
||||
{
|
||||
eFormat = ePixelFormat_BC5;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_R32F)
|
||||
{
|
||||
eFormat = ePixelFormat_R32F;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_G32R32F)
|
||||
{
|
||||
eFormat = ePixelFormat_R32G32F;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_A32B32G32R32F)
|
||||
{
|
||||
eFormat = ePixelFormat_R32G32B32A32F;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_R16F)
|
||||
{
|
||||
eFormat = ePixelFormat_R16F;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_G16R16F)
|
||||
{
|
||||
eFormat = ePixelFormat_R16G16F;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_A16B16G16R16F)
|
||||
{
|
||||
eFormat = ePixelFormat_R16G16B16A16F;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_A16B16G16R16)
|
||||
{
|
||||
eFormat = ePixelFormat_R16G16B16A16;
|
||||
}
|
||||
else if ((header.ddspf.dwFlags == DDS_RGBA || header.ddspf.dwFlags == DDS_RGB)
|
||||
&& header.ddspf.dwRGBBitCount == 32)
|
||||
{
|
||||
if (header.ddspf.dwRBitMask == 0x00ff0000)
|
||||
{
|
||||
eFormat = ePixelFormat_B8G8R8A8;
|
||||
}
|
||||
else
|
||||
{
|
||||
eFormat = ePixelFormat_R8G8B8A8;
|
||||
}
|
||||
}
|
||||
else if (header.ddspf.dwFlags == DDS_LUMINANCEA && header.ddspf.dwRGBBitCount == 8)
|
||||
{
|
||||
eFormat = ePixelFormat_R8G8;
|
||||
}
|
||||
else if (header.ddspf.dwFlags == DDS_LUMINANCE && header.ddspf.dwRGBBitCount == 8)
|
||||
{
|
||||
eFormat = ePixelFormat_A8;
|
||||
}
|
||||
else if ((header.ddspf.dwFlags == DDS_A || header.ddspf.dwFlags == DDS_A_ONLY || header.ddspf.dwFlags == (DDS_A | DDS_A_ONLY)) && header.ddspf.dwRGBBitCount == 8)
|
||||
{
|
||||
eFormat = ePixelFormat_A8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eFormat == ePixelFormat_Unknown)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Unhandled dds pixel format fourCC: %d, flags: %d",
|
||||
header.ddspf.dwFourCC, header.ddspf.dwFlags);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IImageObject* newImage = IImageObject::CreateImage(dwWidth, dwHeight, dwMips, eFormat);
|
||||
|
||||
if (dwMips != newImage->GetMipCount())
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Mipcount from image data doesn't match image size and pixelformat");
|
||||
delete newImage;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//set properties
|
||||
newImage->SetImageFlags(imageFlags);
|
||||
newImage->SetAverageBrightness(header.fAvgBrightness);
|
||||
newImage->SetColorRange(colMinARGB, colMaxARGB);
|
||||
newImage->SetNumPersistentMips(header.bNumPersistentMips);
|
||||
|
||||
return newImage;
|
||||
}
|
||||
|
||||
|
||||
bool IsExtensionSupported(const char* extension)
|
||||
{
|
||||
QString ext = QString(extension).toLower();
|
||||
@@ -226,215 +31,6 @@ namespace ImageProcessingAtom
|
||||
return ext == "dds";
|
||||
}
|
||||
|
||||
IImageObject* LoadImageFromFileLegacy(const AZStd::string& filename)
|
||||
{
|
||||
AZ::IO::SystemFile file;
|
||||
file.Open(filename.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY);
|
||||
|
||||
AZ::IO::SystemFileStream fileLoadStream(&file, true);
|
||||
if (!fileLoadStream.IsOpen())
|
||||
{
|
||||
AZ_Warning("Image Processing", false, "%s: failed to open file %s", __FUNCTION__, filename.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AZStd::string ext = "";
|
||||
AzFramework::StringFunc::Path::GetExtension(filename.c_str(), ext, false);
|
||||
bool isAlphaImage = (ext == "a");
|
||||
|
||||
IImageObject* imageObj = LoadImageFromFileStreamLegacy(fileLoadStream);
|
||||
|
||||
//load mips from seperated files if it's splitted
|
||||
if (imageObj && imageObj->HasImageFlags(EIF_Splitted))
|
||||
{
|
||||
AZStd::string baseName;
|
||||
if (isAlphaImage)
|
||||
{
|
||||
baseName = filename.substr(0, filename.size() - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
baseName = filename;
|
||||
}
|
||||
|
||||
AZ::u32 externalMipCount = 0;
|
||||
if (imageObj->GetNumPersistentMips() < imageObj->GetMipCount())
|
||||
{
|
||||
externalMipCount = imageObj->GetMipCount() - imageObj->GetNumPersistentMips();
|
||||
}
|
||||
//load other mips from files with number extensions
|
||||
for (AZ::u32 mipIdx = 1; mipIdx <= externalMipCount; mipIdx++)
|
||||
{
|
||||
AZ::u32 mip = externalMipCount - mipIdx;
|
||||
AZStd::string mipFileName = AZStd::string::format("%s.%d%s", baseName.c_str(), mipIdx, isAlphaImage ? "a" : "");
|
||||
|
||||
AZ::IO::SystemFile mipFile;
|
||||
mipFile.Open(mipFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY);
|
||||
|
||||
AZ::IO::SystemFileStream mipFileLoadStream(&mipFile, true);
|
||||
|
||||
if (!mipFileLoadStream.IsOpen())
|
||||
{
|
||||
AZ_Warning("Image Processing", false, "%s: failed to open mip file %s", __FUNCTION__, mipFileName.c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
AZ::u32 pitch;
|
||||
AZ::u8* mem;
|
||||
imageObj->GetImagePointer(mip, mem, pitch);
|
||||
AZ::u32 bufSize = imageObj->GetMipBufSize(mip);
|
||||
mipFileLoadStream.Read(bufSize, mem);
|
||||
}
|
||||
}
|
||||
|
||||
return imageObj;
|
||||
}
|
||||
|
||||
IImageObject* LoadImageFromFileStreamLegacy(AZ::IO::SystemFileStream& fileLoadStream)
|
||||
{
|
||||
if (fileLoadStream.GetLength() - fileLoadStream.GetCurPos() < sizeof(DDS_FILE_DESC_LEGACY))
|
||||
{
|
||||
AZ_Error("Image Processing", false, "%s: Trying to load a none-DDS file", __FUNCTION__);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DDS_FILE_DESC_LEGACY desc;
|
||||
DDS_HEADER_DXT10 exthead;
|
||||
|
||||
AZ::IO::SizeType startPos = fileLoadStream.GetCurPos();
|
||||
fileLoadStream.Read(sizeof(desc.dwMagic), &desc.dwMagic);
|
||||
|
||||
if (desc.dwMagic != FOURCC_DDS)
|
||||
{
|
||||
desc.dwMagic = FOURCC_DDS;
|
||||
//the old cry .a file doesn't have "DDS " in the beginning of the file.
|
||||
//so reset to previous position
|
||||
fileLoadStream.Seek(startPos, AZ::IO::GenericStream::ST_SEEK_BEGIN);
|
||||
}
|
||||
|
||||
fileLoadStream.Read(sizeof(desc.header), &desc.header);
|
||||
|
||||
if (!desc.IsValid())
|
||||
{
|
||||
AZ_Error("Image Processing", false, "%s: Trying to load a none-DDS file", __FUNCTION__);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (desc.header.IsDX10Ext())
|
||||
{
|
||||
fileLoadStream.Read(sizeof(exthead), &exthead);
|
||||
}
|
||||
|
||||
IImageObject* outImage = CreateImageFromHeaderLegacy(desc.header, exthead);
|
||||
|
||||
if (outImage == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//load mip data
|
||||
AZ::u32 mipStart = 0;
|
||||
//There are at least three lowest mips are in the file if it was splitted. This is to load splitted dds file exported by legacy rc.exe
|
||||
int numPersistentMips = outImage->GetNumPersistentMips();
|
||||
if (numPersistentMips == 0 && outImage->HasImageFlags(EIF_Splitted))
|
||||
{
|
||||
outImage->SetNumPersistentMips(3);
|
||||
}
|
||||
|
||||
if (outImage->HasImageFlags(EIF_Splitted)
|
||||
&& outImage->GetMipCount() > outImage->GetNumPersistentMips())
|
||||
{
|
||||
mipStart = outImage->GetMipCount() - outImage->GetNumPersistentMips();
|
||||
}
|
||||
|
||||
AZ::u32 faces = 1;
|
||||
if (outImage->HasImageFlags(EIF_Cubemap))
|
||||
{
|
||||
faces = 6;
|
||||
}
|
||||
|
||||
for (AZ::u32 face = 0; face < faces; face++)
|
||||
{
|
||||
for (AZ::u32 mip = mipStart; mip < outImage->GetMipCount(); ++mip)
|
||||
{
|
||||
AZ::u32 pitch;
|
||||
AZ::u8* mem;
|
||||
outImage->GetImagePointer(mip, mem, pitch);
|
||||
AZ::u32 faceBufSize = outImage->GetMipBufSize(mip) / faces;
|
||||
fileLoadStream.Read(faceBufSize, mem + faceBufSize * face);
|
||||
}
|
||||
}
|
||||
|
||||
return outImage;
|
||||
}
|
||||
|
||||
IImageObject* LoadAttachedImageFromDdsFileLegacy(const AZStd::string& filename, IImageObjectPtr originImage)
|
||||
{
|
||||
if (originImage == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AZ_Assert(originImage->HasImageFlags(EIF_AttachedAlpha),
|
||||
"this function should only be called for origin image loaded from same file with attached alpha flag");
|
||||
|
||||
AZ::IO::SystemFile file;
|
||||
file.Open(filename.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY);
|
||||
|
||||
AZ::IO::SystemFileStream fileLoadStream(&file, true);
|
||||
if (!fileLoadStream.IsOpen())
|
||||
{
|
||||
AZ_Warning("Image Processing", false, "%s: failed to open file %s", __FUNCTION__, filename.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DDS_FILE_DESC_LEGACY desc;
|
||||
DDS_HEADER_DXT10 exthead;
|
||||
|
||||
fileLoadStream.Read(sizeof(desc), &desc);
|
||||
if (desc.dwMagic != FOURCC_DDS)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "%s:Trying to load a none-DDS file", __FUNCTION__);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (desc.header.IsDX10Ext())
|
||||
{
|
||||
fileLoadStream.Read(sizeof(exthead), &exthead);
|
||||
}
|
||||
|
||||
//skip size for originImage's mip data
|
||||
for (AZ::u32 mip = 0; mip < originImage->GetMipCount(); ++mip)
|
||||
{
|
||||
AZ::u32 bufSize = originImage->GetMipBufSize(mip);
|
||||
fileLoadStream.Seek(bufSize, AZ::IO::GenericStream::ST_SEEK_CUR);
|
||||
}
|
||||
|
||||
IImageObject* alphaImage = nullptr;
|
||||
|
||||
AZ::u32 marker = 0;
|
||||
fileLoadStream.Read(4, &marker);
|
||||
if (marker == FOURCC_CExt) // marker for the start of O3DE Extended data
|
||||
{
|
||||
fileLoadStream.Read(4, &marker);
|
||||
if (FOURCC_AttC == marker) // Attached Channel chunk
|
||||
{
|
||||
AZ::u32 size = 0;
|
||||
fileLoadStream.Read(4, &size);
|
||||
|
||||
alphaImage = LoadImageFromFileStreamLegacy(fileLoadStream);
|
||||
fileLoadStream.Read(4, &marker);
|
||||
}
|
||||
|
||||
if (FOURCC_CEnd == marker) // marker for the end of O3DE Extended data
|
||||
{
|
||||
fileLoadStream.Read(4, &marker);
|
||||
}
|
||||
}
|
||||
|
||||
return alphaImage;
|
||||
}
|
||||
|
||||
// Create an image object from standard dds header
|
||||
IImageObject* CreateImageFromHeader(DDS_HEADER& header, DDS_HEADER_DXT10& exthead)
|
||||
{
|
||||
@@ -526,45 +122,14 @@ namespace ImageProcessingAtom
|
||||
{
|
||||
format = ePixelFormat_BC1;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == FOURCC_DXT5)
|
||||
else if (header.ddspf.dwFourCC == FOURCC_DXT5 || header.ddspf.dwFourCC == FOURCC_DXT4)
|
||||
{
|
||||
format = ePixelFormat_BC3;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == FOURCC_3DCP)
|
||||
else
|
||||
{
|
||||
format = ePixelFormat_BC4;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == FOURCC_3DC)
|
||||
{
|
||||
format = ePixelFormat_BC5;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_R32F)
|
||||
{
|
||||
format = ePixelFormat_R32F;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_G32R32F)
|
||||
{
|
||||
format = ePixelFormat_R32G32F;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_A32B32G32R32F)
|
||||
{
|
||||
format = ePixelFormat_R32G32B32A32F;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_R16F)
|
||||
{
|
||||
format = ePixelFormat_R16F;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_G16R16F)
|
||||
{
|
||||
format = ePixelFormat_R16G16F;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_A16B16G16R16F)
|
||||
{
|
||||
format = ePixelFormat_R16G16B16A16F;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == DDS_FOURCC_A16B16G16R16)
|
||||
{
|
||||
format = ePixelFormat_R16G16B16A16;
|
||||
AZ_Error("Image Processing", false, "unsupported fourCC format: 0x%x", header.ddspf.dwFourCC);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -44,11 +44,6 @@ namespace ImageProcessingAtom
|
||||
{
|
||||
bool IsExtensionSupported(const char* extension);
|
||||
IImageObject* LoadImageFromFile(const AZStd::string& filename);
|
||||
|
||||
// These functions are for loading legacy O3DE dds files
|
||||
IImageObject* LoadImageFromFileLegacy(const AZStd::string& filename);
|
||||
IImageObject* LoadImageFromFileStreamLegacy(AZ::IO::SystemFileStream& fileLoadStream);
|
||||
IImageObject* LoadAttachedImageFromDdsFileLegacy(const AZStd::string& filename, IImageObjectPtr originImage);
|
||||
};// namespace DdsLoader
|
||||
|
||||
// Load .exr files to an image object
|
||||
|
||||
@@ -5,8 +5,3 @@
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(LY_COMPILE_OPTIONS
|
||||
PRIVATE
|
||||
-fexceptions #ImageLoader/ExrLoader.cpp and PVRTC.cpp uses exceptions
|
||||
)
|
||||
|
||||
@@ -237,14 +237,8 @@ namespace ImageProcessingAtom
|
||||
const static AZ::u32 FOURCC_CEnd = IMAGE_BUIDER_MAKEFOURCC('C', 'E', 'n', 'd'); // O3DE extension end
|
||||
const static AZ::u32 FOURCC_AttC = IMAGE_BUIDER_MAKEFOURCC('A', 't', 't', 'C'); // Chunk Attached Channel
|
||||
|
||||
//Fourcc for pixel formats which aren't supported by dx10, such as astc formats, etc formats, pvrtc formats
|
||||
//Fourcc for pixel formats which aren't supported by dx10, such as astc formats
|
||||
//They are used for dwFourCC of dds header's DDS_PIXELFORMAT to identify non-dx10 pixel formats
|
||||
const static AZ::u32 FOURCC_EAC_R11 = IMAGE_BUIDER_MAKEFOURCC('E', 'A', 'R', ' ');
|
||||
const static AZ::u32 FOURCC_EAC_RG11 = IMAGE_BUIDER_MAKEFOURCC('E', 'A', 'R', 'G');
|
||||
const static AZ::u32 FOURCC_ETC2 = IMAGE_BUIDER_MAKEFOURCC('E', 'T', '2', ' ');
|
||||
const static AZ::u32 FOURCC_ETC2A = IMAGE_BUIDER_MAKEFOURCC('E', 'T', '2', 'A');
|
||||
const static AZ::u32 FOURCC_PVRTC2 = IMAGE_BUIDER_MAKEFOURCC('P', 'V', 'R', '2');
|
||||
const static AZ::u32 FOURCC_PVRTC4 = IMAGE_BUIDER_MAKEFOURCC('P', 'V', 'R', '4');
|
||||
const static AZ::u32 FOURCC_ASTC_4x4 = IMAGE_BUIDER_MAKEFOURCC('A', 'S', '4', '4');
|
||||
const static AZ::u32 FOURCC_ASTC_5x4 = IMAGE_BUIDER_MAKEFOURCC('A', 'S', '5', '4');
|
||||
const static AZ::u32 FOURCC_ASTC_5x5 = IMAGE_BUIDER_MAKEFOURCC('A', 'S', '5', '5');
|
||||
@@ -260,10 +254,10 @@ namespace ImageProcessingAtom
|
||||
const static AZ::u32 FOURCC_ASTC_12x10 = IMAGE_BUIDER_MAKEFOURCC('A', 'S', 'C', 'A');
|
||||
const static AZ::u32 FOURCC_ASTC_12x12 = IMAGE_BUIDER_MAKEFOURCC('A', 'S', 'C', 'C');
|
||||
|
||||
//legacy formats names. they are only used for load rc.exe's dds formats
|
||||
//legacy formats names. they are only used for load old dds formats.
|
||||
const static AZ::u32 FOURCC_DXT1 = IMAGE_BUIDER_MAKEFOURCC('D', 'X', 'T', '1');
|
||||
const static AZ::u32 FOURCC_DXT2 = IMAGE_BUIDER_MAKEFOURCC('D', 'X', 'T', '2');
|
||||
const static AZ::u32 FOURCC_DXT3 = IMAGE_BUIDER_MAKEFOURCC('D', 'X', 'T', '3');
|
||||
const static AZ::u32 FOURCC_DXT4 = IMAGE_BUIDER_MAKEFOURCC('D', 'X', 'T', '4');
|
||||
const static AZ::u32 FOURCC_DXT5 = IMAGE_BUIDER_MAKEFOURCC('D', 'X', 'T', '5');
|
||||
const static AZ::u32 FOURCC_3DCP = IMAGE_BUIDER_MAKEFOURCC('A', 'T', 'I', '1');
|
||||
const static AZ::u32 FOURCC_3DC = IMAGE_BUIDER_MAKEFOURCC('A', 'T', 'I', '2');
|
||||
}
|
||||
|
||||
@@ -52,19 +52,6 @@ namespace ImageProcessingAtom
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsETCFormat(EPixelFormat fmt)
|
||||
{
|
||||
if (fmt == ePixelFormat_ETC2
|
||||
|| fmt == ePixelFormat_ETC2a
|
||||
|| fmt == ePixelFormat_ETC2a1
|
||||
|| fmt == ePixelFormat_EAC_R11
|
||||
|| fmt == ePixelFormat_EAC_RG11)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PixelFormatInfo::PixelFormatInfo(
|
||||
uint32_t a_bitsPerPixel,
|
||||
uint32_t a_Channels,
|
||||
@@ -96,7 +83,6 @@ namespace ImageProcessingAtom
|
||||
, fourCC(a_fourCC)
|
||||
, eSampleType(a_eSampleType)
|
||||
, szName(a_szName)
|
||||
, szLegacyName(a_szName)
|
||||
, szDescription(a_szDescription)
|
||||
, bCompressed(a_bCompressed)
|
||||
, bSelectable(a_bSelectable)
|
||||
@@ -122,15 +108,6 @@ namespace ImageProcessingAtom
|
||||
CPixelFormats::CPixelFormats()
|
||||
{
|
||||
InitPixelFormats();
|
||||
|
||||
m_removedLegacyFormats["DXT1"] = ePixelFormat_BC1;
|
||||
m_removedLegacyFormats["DXT1a"] = ePixelFormat_BC1a;
|
||||
m_removedLegacyFormats["DXT3"] = ePixelFormat_BC3;
|
||||
m_removedLegacyFormats["DXT3t"] = ePixelFormat_BC3t;
|
||||
m_removedLegacyFormats["DXT5"] = ePixelFormat_BC3;
|
||||
m_removedLegacyFormats["DXT5t"] = ePixelFormat_BC3t;
|
||||
m_removedLegacyFormats["3DCp"] = ePixelFormat_BC4;
|
||||
m_removedLegacyFormats["3DC"] = ePixelFormat_BC5;
|
||||
}
|
||||
|
||||
void CPixelFormats::InitPixelFormat(EPixelFormat format, const PixelFormatInfo& formatInfo)
|
||||
@@ -176,13 +153,6 @@ namespace ImageProcessingAtom
|
||||
InitPixelFormat(ePixelFormat_ASTC_10x10, PixelFormatInfo(0, 4, true, "?", 16, 16, 10, 10, 128, false, DXGI_FORMAT_UNKNOWN, FOURCC_ASTC_10x10, ESampleType::eSampleType_Compressed, "ASTC_10x10", "ASTC 10x10 compressed texture format", true, false));
|
||||
InitPixelFormat(ePixelFormat_ASTC_12x10, PixelFormatInfo(0, 4, true, "?", 16, 16, 12, 10, 128, false, DXGI_FORMAT_UNKNOWN, FOURCC_ASTC_12x10, ESampleType::eSampleType_Compressed, "ASTC_12x10", "ASTC 12x10 compressed texture format", true, false));
|
||||
InitPixelFormat(ePixelFormat_ASTC_12x12, PixelFormatInfo(0, 4, true, "?", 16, 16, 12, 12, 128, false, DXGI_FORMAT_UNKNOWN, FOURCC_ASTC_12x12, ESampleType::eSampleType_Compressed, "ASTC_12x12", "ASTC 12x12 compressed texture format", true, false));
|
||||
InitPixelFormat(ePixelFormat_PVRTC2, PixelFormatInfo(2, 4, true, "2", 16, 16, 8, 4, 64, true, DXGI_FORMAT_UNKNOWN, FOURCC_PVRTC2, ESampleType::eSampleType_Compressed, "PVRTC2", "POWERVR 2 bpp compressed texture format", true, false));
|
||||
InitPixelFormat(ePixelFormat_PVRTC4, PixelFormatInfo(4, 4, true, "2", 8, 8, 4, 4, 64, true, DXGI_FORMAT_UNKNOWN, FOURCC_PVRTC4, ESampleType::eSampleType_Compressed, "PVRTC4", "POWERVR 4 bpp compressed texture format", true, false));
|
||||
InitPixelFormat(ePixelFormat_EAC_R11, PixelFormatInfo(4, 1, true, "4", 4, 4, 4, 4, 64, false, DXGI_FORMAT_UNKNOWN, FOURCC_EAC_R11, ESampleType::eSampleType_Compressed, "EAC_R11", "EAC 4 bpp single channel texture format", true, false));
|
||||
InitPixelFormat(ePixelFormat_EAC_RG11, PixelFormatInfo(8, 2, false, "0", 4, 4, 4, 4, 128, false, DXGI_FORMAT_UNKNOWN, FOURCC_EAC_RG11, ESampleType::eSampleType_Compressed, "EAC_RG11", "EAC 8 bpp dual channel texture format", true, false));
|
||||
InitPixelFormat(ePixelFormat_ETC2, PixelFormatInfo(4, 3, false, "0", 4, 4, 4, 4, 64, false, DXGI_FORMAT_UNKNOWN, FOURCC_ETC2, ESampleType::eSampleType_Compressed, "ETC2", "ETC2 RGB 4 bpp compressed texture format", true, false));
|
||||
InitPixelFormat(ePixelFormat_ETC2a, PixelFormatInfo(8, 4, true, "4", 4, 4, 4, 4, 128, false, DXGI_FORMAT_UNKNOWN, FOURCC_ETC2A, ESampleType::eSampleType_Compressed, "ETC2a", "ETC2 RGBA 8 bpp compressed texture format", true, false));
|
||||
InitPixelFormat(ePixelFormat_ETC2a1, PixelFormatInfo(4, 4, true, "1", 4, 4, 4, 4, 64, false, DXGI_FORMAT_UNKNOWN, FOURCC_ETC2A, ESampleType::eSampleType_Compressed, "ETC2a1", "ETC2 RGBA1 8 bpp compressed texture format", true, false));
|
||||
|
||||
// Standardized Compressed DXGI Formats (DX10+)
|
||||
// Data in these compressed formats is hardware decodable on all DX10 chips, and manageable with the DX10-API.
|
||||
@@ -216,17 +186,6 @@ namespace ImageProcessingAtom
|
||||
|
||||
InitPixelFormat(ePixelFormat_R32, PixelFormatInfo(32, 1, false, "0", 1, 1, 1, 1, 32, false, DXGI_FORMAT_FORCE_UINT, FOURCC_DX10, ESampleType::eSampleType_Uint32, "R32", "32-bit red only", false, false));
|
||||
|
||||
//Set legacy name it can be used for convertion
|
||||
m_pixelFormatInfo[ePixelFormat_R8G8B8A8].szLegacyName = "A8R8G8B8";
|
||||
m_pixelFormatInfo[ePixelFormat_R8G8B8X8].szLegacyName = "X8R8G8B8";
|
||||
m_pixelFormatInfo[ePixelFormat_R8G8].szLegacyName = "G8R8";
|
||||
m_pixelFormatInfo[ePixelFormat_R16G16B16A16].szLegacyName = "A16B16G16R16";
|
||||
m_pixelFormatInfo[ePixelFormat_R16G16].szLegacyName = "G16R16";
|
||||
m_pixelFormatInfo[ePixelFormat_R32G32B32A32F].szLegacyName = "A32B32G32R32F";
|
||||
m_pixelFormatInfo[ePixelFormat_R32G32F].szLegacyName = "G32R32F";
|
||||
m_pixelFormatInfo[ePixelFormat_R16G16B16A16F].szLegacyName = "A16B16G16R16F";
|
||||
m_pixelFormatInfo[ePixelFormat_R16G16F].szLegacyName = "G16R16F";
|
||||
|
||||
//validate all pixel formats are proper initialized
|
||||
for (int i = 0; i < ePixelFormat_Count; ++i)
|
||||
{
|
||||
@@ -249,23 +208,6 @@ namespace ImageProcessingAtom
|
||||
return ePixelFormat_Unknown;
|
||||
}
|
||||
|
||||
EPixelFormat CPixelFormats::FindPixelFormatByLegacyName(const char* name)
|
||||
{
|
||||
if (m_removedLegacyFormats.find(name) != m_removedLegacyFormats.end())
|
||||
{
|
||||
return m_removedLegacyFormats[name];
|
||||
}
|
||||
|
||||
for (int i = 0; i < ePixelFormat_Count; ++i)
|
||||
{
|
||||
if (azstricmp(m_pixelFormatInfo[i].szLegacyName, name) == 0)
|
||||
{
|
||||
return (EPixelFormat)i;
|
||||
}
|
||||
}
|
||||
return ePixelFormat_Unknown;
|
||||
}
|
||||
|
||||
const PixelFormatInfo* CPixelFormats::GetPixelFormatInfo(EPixelFormat format)
|
||||
{
|
||||
AZ_Assert((format >= 0) && (format < ePixelFormat_Count), "Unsupport pixel format: %d", format);
|
||||
|
||||
@@ -119,7 +119,6 @@ namespace ImageProcessingAtom
|
||||
bool bSquarePow2; // whether the pixel format requires image size be square and power of 2.
|
||||
DXGI_FORMAT d3d10Format; // the mapping d3d10 pixel format
|
||||
ESampleType eSampleType; // the data type used to present pixel
|
||||
const char* szLegacyName; // name used for cryEngine
|
||||
const char* szName; // name for showing in editors
|
||||
const char* szDescription; // description for showing in editors
|
||||
bool bCompressed; // if it's a compressed format
|
||||
@@ -173,10 +172,6 @@ namespace ImageProcessingAtom
|
||||
bool IsFormatSigned(EPixelFormat fmt);
|
||||
bool IsFormatFloatingPoint(EPixelFormat fmt, bool bFullPrecision);
|
||||
|
||||
//find the pixel format for name used by Cry's RC.ini
|
||||
//returns ePixelFormat_Unknown if the name was not found in registed format list
|
||||
EPixelFormat FindPixelFormatByLegacyName(const char* name);
|
||||
|
||||
//find pixel format by its name
|
||||
EPixelFormat FindPixelFormatByName(const char* name);
|
||||
|
||||
@@ -208,9 +203,6 @@ namespace ImageProcessingAtom
|
||||
|
||||
//pixel format name to pixel format enum
|
||||
AZStd::map<AZStd::string, EPixelFormat> m_pixelFormatNameMap;
|
||||
|
||||
// some formats from cryEngine were removed. using this name-pixelFormat mapping to look for new format
|
||||
AZStd::map<AZStd::string, EPixelFormat> m_removedLegacyFormats;
|
||||
};
|
||||
|
||||
template <class TInteger>
|
||||
|
||||
@@ -102,32 +102,6 @@ namespace ImageProcessingAtom
|
||||
case AZ::RHI::Format::ASTC_12x12_UNORM:
|
||||
return ePixelFormat_ASTC_12x12;
|
||||
|
||||
case AZ::RHI::Format::PVRTC2_UNORM_SRGB:
|
||||
isSRGB = true;
|
||||
case AZ::RHI::Format::PVRTC2_UNORM:
|
||||
return ePixelFormat_PVRTC2;
|
||||
case AZ::RHI::Format::PVRTC4_UNORM_SRGB:
|
||||
isSRGB = true;
|
||||
case AZ::RHI::Format::PVRTC4_UNORM:
|
||||
return ePixelFormat_PVRTC4;
|
||||
|
||||
case AZ::RHI::Format::EAC_R11_UNORM:
|
||||
return ePixelFormat_EAC_R11;
|
||||
case AZ::RHI::Format::EAC_RG11_UNORM:
|
||||
return ePixelFormat_EAC_RG11;
|
||||
case AZ::RHI::Format::ETC2_UNORM_SRGB:
|
||||
isSRGB = true;
|
||||
case AZ::RHI::Format::ETC2_UNORM:
|
||||
return ePixelFormat_ETC2;
|
||||
case AZ::RHI::Format::ETC2A_UNORM_SRGB:
|
||||
isSRGB = true;
|
||||
case AZ::RHI::Format::ETC2A_UNORM:
|
||||
return ePixelFormat_ETC2a;
|
||||
case AZ::RHI::Format::ETC2A1_UNORM_SRGB:
|
||||
isSRGB = true;
|
||||
case AZ::RHI::Format::ETC2A1_UNORM:
|
||||
return ePixelFormat_ETC2a1;
|
||||
|
||||
case AZ::RHI::Format::BC1_UNORM_SRGB:
|
||||
isSRGB = true;
|
||||
case AZ::RHI::Format::BC1_UNORM:
|
||||
@@ -225,22 +199,6 @@ namespace ImageProcessingAtom
|
||||
case ePixelFormat_ASTC_12x12:
|
||||
return isSrgb ? RHI::Format::ASTC_12x12_UNORM_SRGB : RHI::Format::ASTC_12x12_UNORM;
|
||||
|
||||
case ePixelFormat_PVRTC2:
|
||||
return isSrgb ? RHI::Format::PVRTC2_UNORM_SRGB : RHI::Format::PVRTC2_UNORM;
|
||||
case ePixelFormat_PVRTC4:
|
||||
return isSrgb ? RHI::Format::PVRTC4_UNORM_SRGB : RHI::Format::PVRTC4_UNORM;
|
||||
|
||||
case ePixelFormat_EAC_R11:
|
||||
return RHI::Format::EAC_R11_UNORM;
|
||||
case ePixelFormat_EAC_RG11:
|
||||
return RHI::Format::EAC_RG11_UNORM;
|
||||
case ePixelFormat_ETC2:
|
||||
return isSrgb ? RHI::Format::ETC2_UNORM_SRGB : RHI::Format::ETC2_UNORM;
|
||||
case ePixelFormat_ETC2a:
|
||||
return isSrgb ? RHI::Format::ETC2A_UNORM_SRGB : RHI::Format::ETC2A_UNORM;
|
||||
case ePixelFormat_ETC2a1:
|
||||
return isSrgb ? RHI::Format::ETC2A1_UNORM_SRGB : RHI::Format::ETC2A1_UNORM;
|
||||
|
||||
case ePixelFormat_BC1:
|
||||
case ePixelFormat_BC1a:
|
||||
return isSrgb ? RHI::Format::BC1_UNORM_SRGB : RHI::Format::BC1_UNORM;
|
||||
|
||||
@@ -426,60 +426,6 @@ namespace UnitTest
|
||||
return isDifferent;
|
||||
}
|
||||
|
||||
|
||||
bool CompareDDSImage(const QString& imagePath1, const QString& imagePath2, QString& output)
|
||||
{
|
||||
IImageObjectPtr image1, alphaImage1, image2, alphaImage2;
|
||||
|
||||
|
||||
image1 = IImageObjectPtr(DdsLoader::LoadImageFromFileLegacy(imagePath1.toUtf8().constData()));
|
||||
if (image1 && image1->HasImageFlags(EIF_AttachedAlpha))
|
||||
{
|
||||
if (image1->HasImageFlags(EIF_Splitted))
|
||||
{
|
||||
alphaImage1 = IImageObjectPtr(DdsLoader::LoadImageFromFileLegacy(QString(imagePath1 + ".a").toUtf8().constData()));
|
||||
}
|
||||
else
|
||||
{
|
||||
alphaImage1 = IImageObjectPtr(DdsLoader::LoadAttachedImageFromDdsFileLegacy(imagePath1.toUtf8().constData(), image1));
|
||||
}
|
||||
}
|
||||
|
||||
image2 = IImageObjectPtr(DdsLoader::LoadImageFromFileLegacy(imagePath2.toUtf8().constData()));
|
||||
if (image2 && image2->HasImageFlags(EIF_AttachedAlpha))
|
||||
{
|
||||
if (image2->HasImageFlags(EIF_Splitted))
|
||||
{
|
||||
alphaImage2 = IImageObjectPtr(DdsLoader::LoadImageFromFileLegacy(QString(imagePath2 + ".a").toUtf8().constData()));
|
||||
}
|
||||
else
|
||||
{
|
||||
alphaImage2 = IImageObjectPtr(DdsLoader::LoadAttachedImageFromDdsFileLegacy(imagePath2.toUtf8().constData(), image2));
|
||||
}
|
||||
}
|
||||
|
||||
if (!image1 && !image2)
|
||||
{
|
||||
output += "Cannot load both image file! ";
|
||||
return false;
|
||||
}
|
||||
bool isDifferent = false;
|
||||
|
||||
isDifferent = GetComparisonResult(image1, image2, output);
|
||||
|
||||
|
||||
QFileInfo fi(imagePath1);
|
||||
AZStd::string imageName = fi.baseName().toUtf8().constData();
|
||||
SaveImageToFile(image1, imageName + "_new");
|
||||
SaveImageToFile(image2, imageName + "_old");
|
||||
|
||||
if (alphaImage1 || alphaImage2)
|
||||
{
|
||||
isDifferent |= GetComparisonResult(alphaImage1, alphaImage2, output);
|
||||
}
|
||||
|
||||
return isDifferent;
|
||||
}
|
||||
};
|
||||
|
||||
// test CPixelFormats related functions
|
||||
@@ -487,34 +433,6 @@ namespace UnitTest
|
||||
{
|
||||
CPixelFormats& pixelFormats = CPixelFormats::GetInstance();
|
||||
|
||||
//verify names which was used for legacy rc.ini
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC7t") == ePixelFormat_BC7t);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("ETC2A") == ePixelFormat_ETC2a);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("PVRTC4") == ePixelFormat_PVRTC4);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC1") == ePixelFormat_BC1);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("ETC2") == ePixelFormat_ETC2);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC1a") == ePixelFormat_BC1a);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC3") == ePixelFormat_BC3);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC7") == ePixelFormat_BC7);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC5s") == ePixelFormat_BC5s);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("EAC_RG11") == ePixelFormat_EAC_RG11);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC4") == ePixelFormat_BC4);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("EAC_R11") == ePixelFormat_EAC_R11);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("A8R8G8B8") == ePixelFormat_R8G8B8A8);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC6UH") == ePixelFormat_BC6UH);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("R9G9B9E5") == ePixelFormat_R9G9B9E5);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("X8R8G8B8") == ePixelFormat_R8G8B8X8);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("A16B16G16R16F") == ePixelFormat_R16G16B16A16F);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("G8R8") == ePixelFormat_R8G8);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("G16R16") == ePixelFormat_R16G16);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("G16R16F") == ePixelFormat_R16G16F);
|
||||
|
||||
//some legacy format need to be mapping to new format.
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("DXT1") == ePixelFormat_BC1);
|
||||
ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("DXT5") == ePixelFormat_BC3);
|
||||
|
||||
//calculate mipmap count. no cubemap support at this moment
|
||||
|
||||
//for all the non-compressed textures, if there minimum required texture size is 1x1
|
||||
for (uint32 i = 0; i < ePixelFormat_Count; i++)
|
||||
{
|
||||
@@ -543,13 +461,6 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
//check function IsImageSizeValid && EvaluateImageDataSize function
|
||||
ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_PVRTC4, 2, 1, false) == false);
|
||||
ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_PVRTC4, 4, 4, false) == false);
|
||||
ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_PVRTC4, 16, 16, false) == true);
|
||||
ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_PVRTC4, 16, 32, false) == false);
|
||||
ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_PVRTC4, 34, 34, false) == false);
|
||||
ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_PVRTC4, 256, 256, false) == true);
|
||||
|
||||
ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_BC1, 2, 1, false) == false);
|
||||
ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_BC1, 16, 16, false) == true);
|
||||
ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_BC1, 16, 32, false) == true);
|
||||
@@ -834,9 +745,7 @@ namespace UnitTest
|
||||
if (formatInfo->bCompressed)
|
||||
{
|
||||
// skip ASTC formats which are tested in TestConvertASTCCompressor
|
||||
if (!IsASTCFormat(pixelFormat)
|
||||
&& pixelFormat != ePixelFormat_PVRTC2 && pixelFormat != ePixelFormat_PVRTC4
|
||||
&& !IsETCFormat(pixelFormat)) // skip ETC since it's very slow
|
||||
if (!IsASTCFormat(pixelFormat))
|
||||
{
|
||||
compressedFormats.push_back(pixelFormat);
|
||||
}
|
||||
@@ -1112,55 +1021,6 @@ namespace UnitTest
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ImageProcessingTest, DISABLED_CompareOutputImage)
|
||||
{
|
||||
AZStd::string curretTextureFolder = "../TestAssets/TextureAssets/assets_new/textures";
|
||||
AZStd::string oldTextureFolder = "../TestAssets/TextureAssets/assets_old/textures";
|
||||
bool outputOnlyDifferent = false;
|
||||
QDirIterator it(curretTextureFolder.c_str(), QStringList() << "*.dds", QDir::Files, QDirIterator::Subdirectories);
|
||||
QFile f("../texture_comparison_output.csv");
|
||||
f.open(QIODevice::ReadWrite | QIODevice::Truncate);
|
||||
// Write a header for csv file
|
||||
f.write("Texture Name, Path, Mip new/old, MipDiff, Format new/old, Flag new/old, MemSize new/old, MemDiff, Error, AlphaMip new/old, AlphaMipDiff, AlphaFormat new/old, AlphaFlag new/old, AlphaMemSize new/old, AlphaMemDiff, AlphaError\r\n");
|
||||
int i = 0;
|
||||
while (it.hasNext())
|
||||
{
|
||||
i++;
|
||||
it.next();
|
||||
|
||||
QString fileName = it.fileName();
|
||||
QString newFilePath = it.filePath();
|
||||
QString sharedPath = QString(newFilePath).remove(curretTextureFolder.c_str());
|
||||
QString oldFilePath = QString(oldTextureFolder.c_str()) + sharedPath;
|
||||
QString output;
|
||||
if (QFile::exists(oldFilePath))
|
||||
{
|
||||
bool isDifferent = CompareDDSImage(newFilePath, oldFilePath, output);
|
||||
if (outputOnlyDifferent && !isDifferent)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
f.write(fileName.toUtf8().constData());
|
||||
f.write(",");
|
||||
f.write(sharedPath.toUtf8().constData());
|
||||
f.write(output.toUtf8().constData());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
f.write(fileName.toUtf8().constData());
|
||||
f.write(",");
|
||||
f.write(sharedPath.toUtf8().constData());
|
||||
output += ",No old file for comparison!";
|
||||
f.write(output.toUtf8().constData());
|
||||
}
|
||||
f.write("\r\n");
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
|
||||
TEST_F(ImageProcessingTest, TextureSettingReflect_SerializingModernDataInAndOut_WritesAndParsesFileAccurately)
|
||||
{
|
||||
AZStd::string filepath = "test.xml";
|
||||
|
||||
@@ -120,10 +120,6 @@ set(FILES
|
||||
Source/Compressors/Compressor.cpp
|
||||
Source/Compressors/CTSquisher.h
|
||||
Source/Compressors/CTSquisher.cpp
|
||||
Source/Compressors/PVRTC.cpp
|
||||
Source/Compressors/PVRTC.h
|
||||
Source/Compressors/ETC2.cpp
|
||||
Source/Compressors/ETC2.h
|
||||
Source/Compressors/CryTextureSquisher/ColorBlockRGBA4x4f.cpp
|
||||
Source/Compressors/CryTextureSquisher/ColorBlockRGBA4x4s.cpp
|
||||
Source/Compressors/CryTextureSquisher/ColorBlockRGBA4x4c.cpp
|
||||
|
||||
@@ -86,6 +86,13 @@ namespace AZ
|
||||
|
||||
PhysicalDeviceDriverValidator::ValidationResult PhysicalDeviceDriverValidator::ValidateDriverVersion(const PhysicalDeviceDescriptor& descriptor) const
|
||||
{
|
||||
// [GFX TODO] Add driver info for other platforms besides Windows. Currently, avoid spamming warnings.
|
||||
// ATOM-14967 [RHI][Metal] - Address driver version validator for Mac
|
||||
if (m_driverInfo.size() == 0)
|
||||
{
|
||||
return ValidationResult::MissingInfo;
|
||||
}
|
||||
|
||||
auto iter = m_driverInfo.find(descriptor.m_vendorId);
|
||||
|
||||
if (iter == m_driverInfo.end())
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
{
|
||||
"O3DE":
|
||||
{
|
||||
"Atom":
|
||||
{
|
||||
"RHI":
|
||||
{
|
||||
"PhysicalDeviceDriverInfo":
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
{
|
||||
"O3DE":
|
||||
{
|
||||
"Atom":
|
||||
{
|
||||
"RHI":
|
||||
{
|
||||
"PhysicalDeviceDriverInfo":
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
{
|
||||
"O3DE":
|
||||
{
|
||||
"Atom":
|
||||
{
|
||||
"RHI":
|
||||
{
|
||||
"PhysicalDeviceDriverInfo":
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
{
|
||||
"O3DE":
|
||||
{
|
||||
"Atom":
|
||||
{
|
||||
"RHI":
|
||||
{
|
||||
"PhysicalDeviceDriverInfo":
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,11 +54,21 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
Tools
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
AZ::AzCore
|
||||
Gem::EMotionFX_Atom.Static
|
||||
Gem::EMotionFX.Editor.Static
|
||||
Gem::AtomToolsFramework.Static
|
||||
Gem::AtomToolsFramework.Editor
|
||||
Gem::Atom_Component_DebugCamera.Static
|
||||
Gem::Atom_Feature_Common.Static
|
||||
Gem::AtomLyIntegration_CommonFeatures.Static
|
||||
RUNTIME_DEPENDENCIES
|
||||
Gem::EMotionFX.Editor
|
||||
COMPILE_DEFINITIONS
|
||||
PUBLIC
|
||||
EMOTIONFXATOM_EDITOR
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/Module/Module.h>
|
||||
#ifdef EMOTIONFXATOM_EDITOR
|
||||
#include <Editor/EditorSystemComponent.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -28,7 +31,10 @@ namespace AZ
|
||||
: Module()
|
||||
{
|
||||
m_descriptors.insert(m_descriptors.end(), {
|
||||
ActorSystemComponent::CreateDescriptor()
|
||||
ActorSystemComponent::CreateDescriptor(),
|
||||
#ifdef EMOTIONFXATOM_EDITOR
|
||||
EMotionFXAtom::EditorSystemComponent::CreateDescriptor(),
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
@@ -39,6 +45,9 @@ namespace AZ
|
||||
{
|
||||
return ComponentTypeList{
|
||||
azrtti_typeid<ActorSystemComponent>(),
|
||||
#ifdef EMOTIONFXATOM_EDITOR
|
||||
azrtti_typeid<EMotionFXAtom::EditorSystemComponent>(),
|
||||
#endif
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 <Editor/EditorSystemComponent.h>
|
||||
#include <EMStudio/AtomRenderPlugin.h>
|
||||
|
||||
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
|
||||
|
||||
namespace AZ::EMotionFXAtom
|
||||
{
|
||||
void EditorSystemComponent::Reflect(ReflectContext* context)
|
||||
{
|
||||
if (SerializeContext* serialize = azrtti_cast<SerializeContext*>(context))
|
||||
{
|
||||
serialize->Class<EditorSystemComponent, Component>()->Version(0);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSystemComponent::Activate()
|
||||
{
|
||||
EMotionFX::Integration::SystemNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void EditorSystemComponent::Deactivate()
|
||||
{
|
||||
EMotionFX::Integration::SystemNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void EditorSystemComponent::OnRegisterPlugin()
|
||||
{
|
||||
EMStudio::PluginManager* pluginManager = EMStudio::EMStudioManager::GetInstance()->GetPluginManager();
|
||||
pluginManager->RegisterPlugin(aznew EMStudio::AtomRenderPlugin());
|
||||
}
|
||||
} // namespace AZ::EMotionFXAtom
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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/Component/Component.h>
|
||||
#include <Integration/AnimationBus.h>
|
||||
|
||||
namespace AZ::EMotionFXAtom
|
||||
{
|
||||
class EditorSystemComponent
|
||||
: public Component
|
||||
, private EMotionFX::Integration::SystemNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(EditorSystemComponent, "{1FAEC046-255D-4664-8F12-D16503C34431}");
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
protected:
|
||||
// AZ::Component overrides
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
|
||||
// SystemNotificationBus::OnRegisterPlugin
|
||||
void OnRegisterPlugin() override;
|
||||
};
|
||||
} // namespace AZ::EMotionFXAtom
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* 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 <AzFramework/Entity/GameEntityContextBus.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
|
||||
#include <Integration/ActorComponentBus.h>
|
||||
#include <Integration/Components/ActorComponent.h>
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
#include <Atom/RPI.Public/RenderPipeline.h>
|
||||
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
|
||||
#include <Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/DisplayMapper/DisplayMapperFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/PostProcess/PostProcessFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/ImageBasedLights/ImageBasedLightFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/Mesh/MeshFeatureProcessorInterface.h>
|
||||
#include <Atom/Component/DebugCamera/CameraComponent.h>
|
||||
#include <Atom/Component/DebugCamera/NoClipControllerComponent.h>
|
||||
|
||||
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentConstants.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Grid/GridComponentConstants.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Grid/GridComponentConfig.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentConstants.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/PostProcess/PostFxLayerComponentConstants.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/PostProcess/ExposureControl/ExposureControlComponentConstants.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/ImageBasedLights/ImageBasedLightComponentConstants.h>
|
||||
|
||||
#include <EMStudio/AnimViewportRenderer.h>
|
||||
#include <EMotionFX/Source/EMotionFXManager.h>
|
||||
#include <EMotionFX/Source/ActorManager.h>
|
||||
#include <EMotionFX/CommandSystem/Source/CommandManager.h>
|
||||
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
|
||||
|
||||
|
||||
namespace EMStudio
|
||||
{
|
||||
static constexpr float DepthNear = 0.01f;
|
||||
|
||||
AnimViewportRenderer::AnimViewportRenderer(AZ::RPI::ViewportContextPtr viewportContext)
|
||||
: m_windowContext(viewportContext->GetWindowContext())
|
||||
{
|
||||
// Create a new entity context
|
||||
m_entityContext = AZStd::make_unique<AzFramework::EntityContext>();
|
||||
m_entityContext->InitContext();
|
||||
|
||||
// Create the scene
|
||||
auto sceneSystem = AzFramework::SceneSystemInterface::Get();
|
||||
AZ_Assert(sceneSystem, "Unable to retrieve scene system.");
|
||||
AZ::Outcome<AZStd::shared_ptr<AzFramework::Scene>, AZStd::string> createSceneOutcome = sceneSystem->CreateScene("AnimViewport");
|
||||
AZ_Assert(createSceneOutcome, "%s", createSceneOutcome.GetError().data());
|
||||
m_frameworkScene = createSceneOutcome.TakeValue();
|
||||
m_frameworkScene->SetSubsystem<AzFramework::EntityContext::SceneStorageType>(m_entityContext.get());
|
||||
|
||||
// Create and register a scene with all available feature processors
|
||||
AZ::RPI::SceneDescriptor sceneDesc;
|
||||
m_scene = AZ::RPI::Scene::CreateScene(sceneDesc);
|
||||
m_scene->EnableAllFeatureProcessors();
|
||||
|
||||
// Link our RPI::Scene to the AzFramework::Scene
|
||||
m_frameworkScene->SetSubsystem(m_scene);
|
||||
|
||||
// Create a render pipeline from the specified asset for the window context and add the pipeline to the scene
|
||||
AZStd::string defaultPipelineAssetPath = "passes/MainRenderPipeline.azasset";
|
||||
AZ::Data::Asset<AZ::RPI::AnyAsset> pipelineAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath<AZ::RPI::AnyAsset>(
|
||||
defaultPipelineAssetPath.c_str(), AZ::RPI::AssetUtils::TraceLevel::Error);
|
||||
m_renderPipeline = AZ::RPI::RenderPipeline::CreateRenderPipelineForWindow(pipelineAsset, *m_windowContext.get());
|
||||
pipelineAsset.Release();
|
||||
m_scene->AddRenderPipeline(m_renderPipeline);
|
||||
m_renderPipeline->SetDefaultView(viewportContext->GetDefaultView());
|
||||
|
||||
// Currently the scene has to be activated after render pipeline was added so some feature processors (i.e. imgui) can be
|
||||
// initialized properly with pipeline's pass information.
|
||||
m_scene->Activate();
|
||||
AZ::RPI::RPISystemInterface::Get()->RegisterScene(m_scene);
|
||||
AzFramework::EntityContextId entityContextId = m_entityContext->GetContextId();
|
||||
|
||||
// Get the FeatureProcessors
|
||||
m_meshFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::MeshFeatureProcessorInterface>();
|
||||
|
||||
// Configure tone mapper
|
||||
AzFramework::EntityContextRequestBus::EventResult(
|
||||
m_postProcessEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "postProcessEntity");
|
||||
AZ_Assert(m_postProcessEntity != nullptr, "Failed to create post process entity.");
|
||||
|
||||
m_postProcessEntity->CreateComponent(AZ::Render::PostFxLayerComponentTypeId);
|
||||
m_postProcessEntity->CreateComponent(AZ::Render::ExposureControlComponentTypeId);
|
||||
m_postProcessEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
|
||||
m_postProcessEntity->Activate();
|
||||
|
||||
// Init directional light processor
|
||||
m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::DirectionalLightFeatureProcessorInterface>();
|
||||
|
||||
// Init display mapper processor
|
||||
m_displayMapperFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::DisplayMapperFeatureProcessorInterface>();
|
||||
|
||||
// Init Skybox
|
||||
m_skyboxFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::SkyBoxFeatureProcessorInterface>();
|
||||
m_skyboxFeatureProcessor->Enable(true);
|
||||
m_skyboxFeatureProcessor->SetSkyboxMode(AZ::Render::SkyBoxMode::Cubemap);
|
||||
|
||||
// Create IBL
|
||||
AzFramework::EntityContextRequestBus::EventResult(
|
||||
m_iblEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "IblEntity");
|
||||
AZ_Assert(m_iblEntity != nullptr, "Failed to create ibl entity.");
|
||||
|
||||
m_iblEntity->CreateComponent(AZ::Render::ImageBasedLightComponentTypeId);
|
||||
m_iblEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
|
||||
m_iblEntity->Activate();
|
||||
|
||||
// Load light preset
|
||||
AZ::Data::Asset<AZ::RPI::AnyAsset> lightingPresetAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath<AZ::RPI::AnyAsset>(
|
||||
"lightingpresets/default.lightingpreset.azasset", AZ::RPI::AssetUtils::TraceLevel::Warning);
|
||||
const AZ::Render::LightingPreset* preset = lightingPresetAsset->GetDataAs<AZ::Render::LightingPreset>();
|
||||
SetLightingPreset(preset);
|
||||
|
||||
// Create grid
|
||||
AzFramework::EntityContextRequestBus::EventResult(
|
||||
m_gridEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportGrid");
|
||||
AZ_Assert(m_gridEntity != nullptr, "Failed to create grid entity.");
|
||||
|
||||
AZ::Render::GridComponentConfig gridConfig;
|
||||
gridConfig.m_gridSize = 4.0f;
|
||||
gridConfig.m_axisColor = AZ::Color(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
gridConfig.m_primaryColor = AZ::Color(0.3f, 0.3f, 0.3f, 1.0f);
|
||||
gridConfig.m_secondaryColor = AZ::Color(0.5f, 0.1f, 0.1f, 1.0f);
|
||||
auto gridComponent = m_gridEntity->CreateComponent(AZ::Render::GridComponentTypeId);
|
||||
gridComponent->SetConfiguration(gridConfig);
|
||||
|
||||
m_gridEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
|
||||
m_gridEntity->Activate();
|
||||
|
||||
Reinit();
|
||||
}
|
||||
|
||||
AnimViewportRenderer::~AnimViewportRenderer()
|
||||
{
|
||||
// Destroy all the entity we created.
|
||||
m_entityContext->DestroyEntity(m_iblEntity);
|
||||
m_entityContext->DestroyEntity(m_postProcessEntity);
|
||||
m_entityContext->DestroyEntity(m_gridEntity);
|
||||
for (AZ::Entity* entity : m_actorEntities)
|
||||
{
|
||||
m_entityContext->DestroyEntity(entity);
|
||||
}
|
||||
m_actorEntities.clear();
|
||||
m_entityContext->DestroyContext();
|
||||
|
||||
for (AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle& handle : m_lightHandles)
|
||||
{
|
||||
m_directionalLightFeatureProcessor->ReleaseLight(handle);
|
||||
}
|
||||
m_lightHandles.clear();
|
||||
|
||||
m_frameworkScene->UnsetSubsystem(m_scene);
|
||||
|
||||
auto sceneSystem = AzFramework::SceneSystemInterface::Get();
|
||||
AZ_Assert(sceneSystem, "AtomViewportRenderer was unable to get the scene system during destruction.");
|
||||
bool removeSuccess = sceneSystem->RemoveScene("AnimViewport");
|
||||
if (!removeSuccess)
|
||||
{
|
||||
AZ_Assert(false, "AtomViewportRenderer should be removed.");
|
||||
}
|
||||
|
||||
AZ::RPI::RPISystemInterface::Get()->UnregisterScene(m_scene);
|
||||
m_scene = nullptr;
|
||||
}
|
||||
|
||||
void AnimViewportRenderer::Reinit()
|
||||
{
|
||||
ReinitActorEntities();
|
||||
ResetEnvironment();
|
||||
}
|
||||
|
||||
void AnimViewportRenderer::ResetEnvironment()
|
||||
{
|
||||
// Reset environment
|
||||
AZ::Transform iblTransform = AZ::Transform::CreateIdentity();
|
||||
AZ::TransformBus::Event(m_iblEntity->GetId(), &AZ::TransformBus::Events::SetLocalTM, iblTransform);
|
||||
|
||||
const AZ::Matrix4x4 rotationMatrix = AZ::Matrix4x4::CreateIdentity();
|
||||
AZ::RPI::ScenePtr scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene();
|
||||
auto skyBoxFeatureProcessorInterface = scene->GetFeatureProcessor<AZ::Render::SkyBoxFeatureProcessorInterface>();
|
||||
skyBoxFeatureProcessorInterface->SetCubemapRotationMatrix(rotationMatrix);
|
||||
}
|
||||
|
||||
void AnimViewportRenderer::ReinitActorEntities()
|
||||
{
|
||||
// 1. Destroy all the entities that do not point to any actorAsset anymore.
|
||||
AZStd::set<AZ::Data::AssetId> assetLookup;
|
||||
AzFramework::EntityContext* entityContext = m_entityContext.get();
|
||||
const size_t numActors = EMotionFX::GetActorManager().GetNumActors();
|
||||
for (size_t i = 0; i < numActors; ++i)
|
||||
{
|
||||
assetLookup.emplace(EMotionFX::GetActorManager().GetActorAsset(i).GetId());
|
||||
}
|
||||
m_actorEntities.erase(
|
||||
AZStd::remove_if(
|
||||
m_actorEntities.begin(), m_actorEntities.end(),
|
||||
[&assetLookup, entityContext](AZ::Entity* entity)
|
||||
{
|
||||
EMotionFX::Integration::ActorComponent* actorComponent =
|
||||
entity->FindComponent<EMotionFX::Integration::ActorComponent>();
|
||||
if (assetLookup.find(actorComponent->GetActorAsset().GetId()) == assetLookup.end())
|
||||
{
|
||||
entityContext->DestroyEntity(entity);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
m_actorEntities.end());
|
||||
|
||||
// 2. Create an entity for every actorAsset stored in actor manager.
|
||||
for (size_t i = 0; i < numActors; ++i)
|
||||
{
|
||||
AZ::Data::Asset<EMotionFX::Integration::ActorAsset> actorAsset = EMotionFX::GetActorManager().GetActorAsset(i);
|
||||
if (!actorAsset->IsReady())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AZ::Entity* entity = FindActorEntity(actorAsset);
|
||||
if (!entity)
|
||||
{
|
||||
m_actorEntities.emplace_back(CreateActorEntity(actorAsset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Entity* AnimViewportRenderer::FindActorEntity(AZ::Data::Asset<EMotionFX::Integration::ActorAsset> actorAsset) const
|
||||
{
|
||||
const auto foundEntity = AZStd::find_if(
|
||||
begin(m_actorEntities), end(m_actorEntities),
|
||||
[match = actorAsset](const AZ::Entity* entity)
|
||||
{
|
||||
EMotionFX::Integration::ActorComponent* actorComponent = entity->FindComponent<EMotionFX::Integration::ActorComponent>();
|
||||
return actorComponent->GetActorAsset() == match;
|
||||
});
|
||||
return foundEntity != end(m_actorEntities) ? (*foundEntity) : nullptr;
|
||||
}
|
||||
|
||||
AZ::Entity* AnimViewportRenderer::CreateActorEntity(AZ::Data::Asset<EMotionFX::Integration::ActorAsset> actorAsset)
|
||||
{
|
||||
AZ::Entity* actorEntity = m_entityContext->CreateEntity(actorAsset->GetActor()->GetName());
|
||||
actorEntity->CreateComponent(azrtti_typeid<EMotionFX::Integration::ActorComponent>());
|
||||
actorEntity->CreateComponent(AZ::Render::MaterialComponentTypeId);
|
||||
actorEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
|
||||
actorEntity->Activate();
|
||||
|
||||
EMotionFX::Integration::ActorComponent* actorComponent = actorEntity->FindComponent<EMotionFX::Integration::ActorComponent>();
|
||||
actorComponent->SetActorAsset(actorAsset);
|
||||
|
||||
// Since this entity belongs to the animation editor, we need to set the isOwnByRuntime flag to false.
|
||||
actorComponent->GetActorInstance()->SetIsOwnedByRuntime(false);
|
||||
// Selet the actor instance in the command manager after it has been created.
|
||||
AZStd::string outResult;
|
||||
EMStudioManager::GetInstance()->GetCommandManager()->ExecuteCommandInsideCommand(
|
||||
AZStd::string::format("Select -actorInstanceID %i", actorComponent->GetActorInstance()->GetID()).c_str(), outResult);
|
||||
|
||||
return actorEntity;
|
||||
}
|
||||
|
||||
void AnimViewportRenderer::SetLightingPreset(const AZ::Render::LightingPreset* preset)
|
||||
{
|
||||
if (!preset)
|
||||
{
|
||||
AZ_Warning("AnimViewportRenderer", false, "Attempting to set invalid lighting preset.");
|
||||
return;
|
||||
}
|
||||
|
||||
AZ::Render::ImageBasedLightFeatureProcessorInterface* iblFeatureProcessor =
|
||||
m_scene->GetFeatureProcessor<AZ::Render::ImageBasedLightFeatureProcessorInterface>();
|
||||
AZ::Render::PostProcessFeatureProcessorInterface* postProcessFeatureProcessor =
|
||||
m_scene->GetFeatureProcessor<AZ::Render::PostProcessFeatureProcessorInterface>();
|
||||
AZ::Render::ExposureControlSettingsInterface* exposureControlSettingInterface =
|
||||
postProcessFeatureProcessor->GetOrCreateSettingsInterface(m_postProcessEntity->GetId())
|
||||
->GetOrCreateExposureControlSettingsInterface();
|
||||
|
||||
Camera::Configuration cameraConfig;
|
||||
cameraConfig.m_fovRadians = AZ::Constants::HalfPi;
|
||||
cameraConfig.m_nearClipDistance = DepthNear;
|
||||
|
||||
preset->ApplyLightingPreset(
|
||||
iblFeatureProcessor, m_skyboxFeatureProcessor, exposureControlSettingInterface, m_directionalLightFeatureProcessor,
|
||||
cameraConfig, m_lightHandles, nullptr, AZ::RPI::MaterialPropertyIndex::Null, false);
|
||||
}
|
||||
} // namespace EMStudio
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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/Component/TickBus.h>
|
||||
#include <AzFramework/Windowing/NativeWindow.h>
|
||||
#include <AzFramework/Scene/Scene.h>
|
||||
|
||||
#include <Integration/Assets/ActorAsset.h>
|
||||
#include <Atom/RPI.Public/Base.h>
|
||||
#include <Atom/RPI.Public/ViewportContext.h>
|
||||
#include <Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/Utils/LightingPreset.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class Entity;
|
||||
class Component;
|
||||
|
||||
namespace Render
|
||||
{
|
||||
class DisplayMapperFeatureProcessorInterface;
|
||||
class DirectionalLightFeatureProcessorInterface;
|
||||
class MeshFeatureProcessorInterface;
|
||||
}
|
||||
|
||||
namespace RPI
|
||||
{
|
||||
class WindowContext;
|
||||
}
|
||||
}
|
||||
|
||||
namespace EMStudio
|
||||
{
|
||||
class AnimViewportRenderer
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AnimViewportRenderer, AZ::SystemAllocator, 0);
|
||||
|
||||
AnimViewportRenderer(AZ::RPI::ViewportContextPtr viewportContext);
|
||||
~AnimViewportRenderer();
|
||||
|
||||
void Reinit();
|
||||
|
||||
private:
|
||||
|
||||
// This function resets the light, camera and other environment settings.
|
||||
void ResetEnvironment();
|
||||
|
||||
// This function creates in-editor entities for all actor assets stored in the actor manager,
|
||||
// and deletes all the actor entities that no longer has an actor asset in the actor manager.
|
||||
// Those entities are used in atom render viewport to visualize actors in animation editor.
|
||||
void ReinitActorEntities();
|
||||
|
||||
AZ::Entity* CreateActorEntity(AZ::Data::Asset<EMotionFX::Integration::ActorAsset> actorAsset);
|
||||
|
||||
AZ::Entity* FindActorEntity(AZ::Data::Asset<EMotionFX::Integration::ActorAsset> actorAsset) const;
|
||||
void SetLightingPreset(const AZ::Render::LightingPreset* preset);
|
||||
|
||||
AZStd::shared_ptr<AZ::RPI::WindowContext> m_windowContext;
|
||||
AZStd::unique_ptr<AzFramework::EntityContext> m_entityContext;
|
||||
AZStd::shared_ptr<AzFramework::Scene> m_frameworkScene;
|
||||
AZ::RPI::ScenePtr m_scene;
|
||||
AZ::RPI::RenderPipelinePtr m_renderPipeline;
|
||||
AZ::Render::DirectionalLightFeatureProcessorInterface* m_directionalLightFeatureProcessor = nullptr;
|
||||
AZ::Render::DisplayMapperFeatureProcessorInterface* m_displayMapperFeatureProcessor = nullptr;
|
||||
AZ::Render::SkyBoxFeatureProcessorInterface* m_skyboxFeatureProcessor = nullptr;
|
||||
AZ::Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr;
|
||||
|
||||
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;
|
||||
|
||||
AZStd::vector<AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle> m_lightHandles;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 <EMStudio/AnimViewportSettings.h>
|
||||
|
||||
namespace EMStudio::ViewportUtil
|
||||
{
|
||||
constexpr AZStd::string_view CameraRotateSmoothnessSetting = "/Amazon/Preferences/Editor/Camera/RotateSmoothness";
|
||||
constexpr AZStd::string_view CameraTranslateSmoothnessSetting = "/Amazon/Preferences/Editor/Camera/TranslateSmoothness";
|
||||
constexpr AZStd::string_view CameraTranslateSmoothingSetting = "/Amazon/Preferences/Editor/Camera/TranslateSmoothing";
|
||||
constexpr AZStd::string_view CameraRotateSmoothingSetting = "/Amazon/Preferences/Editor/Camera/RotateSmoothing";
|
||||
|
||||
constexpr AZStd::string_view CameraOrbitLookIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitLookId";
|
||||
constexpr AZStd::string_view CameraTranslateForwardIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateForwardId";
|
||||
constexpr AZStd::string_view CameraTranslateBackwardIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateBackwardId";
|
||||
constexpr AZStd::string_view CameraTranslateLeftIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateLeftId";
|
||||
constexpr AZStd::string_view CameraTranslateRightIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateRightId";
|
||||
constexpr AZStd::string_view CameraTranslateUpIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpId";
|
||||
constexpr AZStd::string_view CameraTranslateDownIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpDownId";
|
||||
constexpr AZStd::string_view CameraTranslateBoostIdSetting = "/Amazon/Preferences/Editor/Camera/TranslateBoostId";
|
||||
|
||||
AzFramework::TranslateCameraInputChannelIds BuildTranslateCameraInputChannelIds()
|
||||
{
|
||||
AzFramework::TranslateCameraInputChannelIds translateCameraInputChannelIds;
|
||||
translateCameraInputChannelIds.m_leftChannelId =
|
||||
AzFramework::InputChannelId(GetRegistry(CameraTranslateLeftIdSetting, AZStd::string("keyboard_key_alphanumeric_A")).c_str());
|
||||
translateCameraInputChannelIds.m_rightChannelId =
|
||||
AzFramework::InputChannelId(GetRegistry(CameraTranslateRightIdSetting, AZStd::string("keyboard_key_alphanumeric_D")).c_str());
|
||||
translateCameraInputChannelIds.m_forwardChannelId =
|
||||
AzFramework::InputChannelId(GetRegistry(CameraTranslateForwardIdSetting, AZStd::string("keyboard_key_alphanumeric_W")).c_str());
|
||||
translateCameraInputChannelIds.m_backwardChannelId = AzFramework::InputChannelId(
|
||||
GetRegistry(CameraTranslateBackwardIdSetting, AZStd::string("keyboard_key_alphanumeric_S")).c_str());
|
||||
translateCameraInputChannelIds.m_upChannelId =
|
||||
AzFramework::InputChannelId(GetRegistry(CameraTranslateUpIdSetting, AZStd::string("keyboard_key_alphanumeric_E")).c_str());
|
||||
translateCameraInputChannelIds.m_downChannelId =
|
||||
AzFramework::InputChannelId(GetRegistry(CameraTranslateDownIdSetting, AZStd::string("keyboard_key_alphanumeric_Q")).c_str());
|
||||
translateCameraInputChannelIds.m_boostChannelId =
|
||||
AzFramework::InputChannelId(GetRegistry(CameraTranslateBoostIdSetting, AZStd::string("keyboard_key_modifier_shift_l")).c_str());
|
||||
|
||||
return translateCameraInputChannelIds;
|
||||
}
|
||||
|
||||
float CameraRotateSmoothness()
|
||||
{
|
||||
return aznumeric_cast<float>(GetRegistry(CameraRotateSmoothnessSetting, 5.0));
|
||||
}
|
||||
|
||||
float CameraTranslateSmoothness()
|
||||
{
|
||||
return aznumeric_cast<float>(GetRegistry(CameraTranslateSmoothnessSetting, 5.0));
|
||||
}
|
||||
|
||||
bool CameraRotateSmoothingEnabled()
|
||||
{
|
||||
return GetRegistry(CameraRotateSmoothingSetting, true);
|
||||
}
|
||||
|
||||
bool CameraTranslateSmoothingEnabled()
|
||||
{
|
||||
return GetRegistry(CameraTranslateSmoothingSetting, true);
|
||||
}
|
||||
|
||||
AzFramework::InputChannelId BuildRotateCameraInputId()
|
||||
{
|
||||
return AzFramework::InputChannelId(GetRegistry(CameraOrbitLookIdSetting, AZStd::string("mouse_button_left")).c_str());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 <AtomToolsFramework/Viewport/ModularViewportCameraController.h>
|
||||
|
||||
namespace EMStudio::ViewportUtil
|
||||
{
|
||||
template<typename T>
|
||||
AZStd::remove_cvref_t<T> GetRegistry(const AZStd::string_view setting, T&& defaultValue)
|
||||
{
|
||||
AZStd::remove_cvref_t<T> value = AZStd::forward<T>(defaultValue);
|
||||
if (const auto* registry = AZ::SettingsRegistry::Get())
|
||||
{
|
||||
T potentialValue;
|
||||
if (registry->Get(potentialValue, setting))
|
||||
{
|
||||
value = AZStd::move(potentialValue);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float CameraRotateSmoothness();
|
||||
float CameraTranslateSmoothness();
|
||||
bool CameraRotateSmoothingEnabled();
|
||||
bool CameraTranslateSmoothingEnabled();
|
||||
|
||||
AzFramework::TranslateCameraInputChannelIds BuildTranslateCameraInputChannelIds();
|
||||
AzFramework::InputChannelId BuildRotateCameraInputId();
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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/Settings/SettingsRegistry.h>
|
||||
#include <AzFramework/Viewport/ViewportControllerList.h>
|
||||
#include <AzFramework/Viewport/CameraInput.h>
|
||||
#include <Atom/RPI.Public/ViewportContext.h>
|
||||
#include <AtomToolsFramework/Viewport/ModularViewportCameraController.h>
|
||||
|
||||
#include <EMStudio/AnimViewportWidget.h>
|
||||
#include <EMStudio/AnimViewportRenderer.h>
|
||||
#include <EMStudio/AnimViewportSettings.h>
|
||||
|
||||
namespace EMStudio
|
||||
{
|
||||
AnimViewportWidget::AnimViewportWidget(QWidget* parent)
|
||||
: AtomToolsFramework::RenderViewportWidget(parent)
|
||||
{
|
||||
setObjectName(QString::fromUtf8("AtomViewportWidget"));
|
||||
QSizePolicy qSize(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
qSize.setHorizontalStretch(0);
|
||||
qSize.setVerticalStretch(0);
|
||||
qSize.setHeightForWidth(sizePolicy().hasHeightForWidth());
|
||||
setSizePolicy(qSize);
|
||||
setAutoFillBackground(false);
|
||||
setStyleSheet(QString::fromUtf8(""));
|
||||
|
||||
m_renderer = AZStd::make_unique<AnimViewportRenderer>(GetViewportContext());
|
||||
|
||||
SetupCameras();
|
||||
SetupCameraController();
|
||||
}
|
||||
|
||||
void AnimViewportWidget::SetupCameras()
|
||||
{
|
||||
m_rotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(EMStudio::ViewportUtil::BuildRotateCameraInputId());
|
||||
|
||||
const auto translateCameraInputChannelIds = EMStudio::ViewportUtil::BuildTranslateCameraInputChannelIds();
|
||||
m_translateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(
|
||||
translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivotLook);
|
||||
m_translateCamera.get()->m_translateSpeedFn = []
|
||||
{
|
||||
return 3.0f;
|
||||
};
|
||||
|
||||
m_orbitDollyScrollCamera = AZStd::make_shared<AzFramework::OrbitDollyScrollCameraInput>();
|
||||
}
|
||||
|
||||
void AnimViewportWidget::SetupCameraController()
|
||||
{
|
||||
auto controller = AZStd::make_shared<AtomToolsFramework::ModularViewportCameraController>();
|
||||
controller->SetCameraViewportContextBuilderCallback(
|
||||
[viewportId =
|
||||
GetViewportContext()->GetId()](AZStd::unique_ptr<AtomToolsFramework::ModularCameraViewportContext>& cameraViewportContext)
|
||||
{
|
||||
cameraViewportContext = AZStd::make_unique<AtomToolsFramework::ModularCameraViewportContextImpl>(viewportId);
|
||||
});
|
||||
|
||||
controller->SetCameraPriorityBuilderCallback(
|
||||
[](AtomToolsFramework::CameraControllerPriorityFn& cameraControllerPriorityFn)
|
||||
{
|
||||
cameraControllerPriorityFn = AtomToolsFramework::DefaultCameraControllerPriority;
|
||||
});
|
||||
|
||||
controller->SetCameraPropsBuilderCallback(
|
||||
[](AzFramework::CameraProps& cameraProps)
|
||||
{
|
||||
cameraProps.m_rotateSmoothnessFn = []
|
||||
{
|
||||
return EMStudio::ViewportUtil::CameraRotateSmoothness();
|
||||
};
|
||||
|
||||
cameraProps.m_translateSmoothnessFn = []
|
||||
{
|
||||
return EMStudio::ViewportUtil::CameraTranslateSmoothness();
|
||||
};
|
||||
|
||||
cameraProps.m_rotateSmoothingEnabledFn = []
|
||||
{
|
||||
return EMStudio::ViewportUtil::CameraRotateSmoothingEnabled();
|
||||
};
|
||||
|
||||
cameraProps.m_translateSmoothingEnabledFn = []
|
||||
{
|
||||
return EMStudio::ViewportUtil::CameraTranslateSmoothingEnabled();
|
||||
};
|
||||
});
|
||||
|
||||
controller->SetCameraListBuilderCallback(
|
||||
[this](AzFramework::Cameras& cameras)
|
||||
{
|
||||
cameras.AddCamera(m_rotateCamera);
|
||||
cameras.AddCamera(m_translateCamera);
|
||||
cameras.AddCamera(m_orbitDollyScrollCamera);
|
||||
});
|
||||
GetControllerList()->Add(controller);
|
||||
}
|
||||
} // namespace EMStudio
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 <AtomToolsFramework/Viewport/RenderViewportWidget.h>
|
||||
#include <AzFramework/Viewport/CameraInput.h>
|
||||
|
||||
namespace EMStudio
|
||||
{
|
||||
class AnimViewportRenderer;
|
||||
|
||||
class AnimViewportWidget
|
||||
: public AtomToolsFramework::RenderViewportWidget
|
||||
{
|
||||
public:
|
||||
AnimViewportWidget(QWidget* parent = nullptr);
|
||||
AnimViewportRenderer* GetAnimViewportRenderer() { return m_renderer.get(); }
|
||||
|
||||
private:
|
||||
void SetupCameras();
|
||||
void SetupCameraController();
|
||||
|
||||
AZStd::unique_ptr<AnimViewportRenderer> m_renderer;
|
||||
AZStd::shared_ptr<AzFramework::RotateCameraInput> m_rotateCamera;
|
||||
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_translateCamera;
|
||||
AZStd::shared_ptr<AzFramework::OrbitDollyScrollCameraInput> m_orbitDollyScrollCamera;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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 <EMStudio/AtomRenderPlugin.h>
|
||||
#include <EMStudio/AnimViewportRenderer.h>
|
||||
|
||||
#include <Integration/Components/ActorComponent.h>
|
||||
#include <EMotionFX/CommandSystem/Source/CommandManager.h>
|
||||
#include <EMotionFX/Source/Allocators.h>
|
||||
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
namespace EMStudio
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(AtomRenderPlugin, EMotionFX::EditorAllocator, 0);
|
||||
|
||||
AtomRenderPlugin::AtomRenderPlugin()
|
||||
: DockWidgetPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
AtomRenderPlugin::~AtomRenderPlugin()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const char* AtomRenderPlugin::GetName() const
|
||||
{
|
||||
return "Atom Render Window (Preview)";
|
||||
}
|
||||
|
||||
uint32 AtomRenderPlugin::GetClassID() const
|
||||
{
|
||||
return static_cast<uint32>(AtomRenderPlugin::CLASS_ID);
|
||||
}
|
||||
|
||||
const char* AtomRenderPlugin::GetCreatorName() const
|
||||
{
|
||||
return "O3DE";
|
||||
}
|
||||
|
||||
float AtomRenderPlugin::GetVersion() const
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
bool AtomRenderPlugin::GetIsClosable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AtomRenderPlugin::GetIsFloatable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AtomRenderPlugin::GetIsVertical() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
EMStudioPlugin* AtomRenderPlugin::Clone()
|
||||
{
|
||||
return new AtomRenderPlugin();
|
||||
}
|
||||
|
||||
EMStudioPlugin::EPluginType AtomRenderPlugin::GetPluginType() const
|
||||
{
|
||||
return EMStudioPlugin::PLUGINTYPE_RENDERING;
|
||||
}
|
||||
|
||||
void AtomRenderPlugin::ReinitRenderer()
|
||||
{
|
||||
m_animViewportWidget->GetAnimViewportRenderer()->Reinit();
|
||||
}
|
||||
|
||||
bool AtomRenderPlugin::Init()
|
||||
{
|
||||
m_innerWidget = new QWidget();
|
||||
m_dock->setWidget(m_innerWidget);
|
||||
|
||||
QVBoxLayout* verticalLayout = new QVBoxLayout(m_innerWidget);
|
||||
verticalLayout->setSizeConstraint(QLayout::SetNoConstraint);
|
||||
verticalLayout->setSpacing(1);
|
||||
verticalLayout->setMargin(0);
|
||||
m_animViewportWidget = new AnimViewportWidget(m_innerWidget);
|
||||
verticalLayout->addWidget(m_animViewportWidget);
|
||||
|
||||
// Register command callbacks.
|
||||
m_importActorCallback = new ImportActorCallback(false);
|
||||
m_removeActorCallback = new RemoveActorCallback(false);
|
||||
EMStudioManager::GetInstance()->GetCommandManager()->RegisterCommandCallback("ImportActor", m_importActorCallback);
|
||||
EMStudioManager::GetInstance()->GetCommandManager()->RegisterCommandCallback("RemoveActor", m_removeActorCallback);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Command callbacks
|
||||
bool ReinitAtomRenderPlugin()
|
||||
{
|
||||
EMStudioPlugin* plugin = EMStudio::GetPluginManager()->FindActivePlugin(static_cast<uint32>(AtomRenderPlugin::CLASS_ID));
|
||||
if (!plugin)
|
||||
{
|
||||
AZ_Error("AtomRenderPlugin", false, "Cannot execute command callback. Atom render plugin does not exist.");
|
||||
return false;
|
||||
}
|
||||
|
||||
AtomRenderPlugin* atomRenderPlugin = static_cast<AtomRenderPlugin*>(plugin);
|
||||
atomRenderPlugin->ReinitRenderer();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AtomRenderPlugin::ImportActorCallback::Execute(
|
||||
[[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine)
|
||||
{
|
||||
return ReinitAtomRenderPlugin();
|
||||
}
|
||||
bool AtomRenderPlugin::ImportActorCallback::Undo(
|
||||
[[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine)
|
||||
{
|
||||
return ReinitAtomRenderPlugin();
|
||||
}
|
||||
|
||||
bool AtomRenderPlugin::RemoveActorCallback::Execute(
|
||||
[[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine)
|
||||
{
|
||||
return ReinitAtomRenderPlugin();
|
||||
}
|
||||
bool AtomRenderPlugin::RemoveActorCallback::Undo(
|
||||
[[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine)
|
||||
{
|
||||
return ReinitAtomRenderPlugin();
|
||||
}
|
||||
}// namespace EMStudio
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <MCore/Source/Command.h>
|
||||
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.h>
|
||||
|
||||
#include <EMStudio/AnimViewportWidget.h>
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class Entity;
|
||||
}
|
||||
|
||||
namespace EMStudio
|
||||
{
|
||||
class AtomRenderPlugin
|
||||
: public DockWidgetPlugin
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR_DECL
|
||||
|
||||
enum
|
||||
{
|
||||
CLASS_ID = 0x32b0c04d
|
||||
};
|
||||
AtomRenderPlugin();
|
||||
~AtomRenderPlugin();
|
||||
|
||||
// Plugin information
|
||||
const char* GetName() const override;
|
||||
uint32 GetClassID() const override;
|
||||
const char* GetCreatorName() const override;
|
||||
float GetVersion() const override;
|
||||
bool GetIsClosable() const override;
|
||||
bool GetIsFloatable() const override;
|
||||
bool GetIsVertical() const override;
|
||||
bool Init() override;
|
||||
EMStudioPlugin* Clone();
|
||||
EMStudioPlugin::EPluginType GetPluginType() const override;
|
||||
|
||||
void ReinitRenderer();
|
||||
|
||||
private:
|
||||
MCORE_DEFINECOMMANDCALLBACK(ImportActorCallback);
|
||||
MCORE_DEFINECOMMANDCALLBACK(RemoveActorCallback);
|
||||
ImportActorCallback* m_importActorCallback = nullptr;
|
||||
RemoveActorCallback* m_removeActorCallback = nullptr;
|
||||
QWidget* m_innerWidget = nullptr;
|
||||
AnimViewportWidget* m_animViewportWidget = nullptr;
|
||||
};
|
||||
}// namespace EMStudio
|
||||
@@ -8,4 +8,14 @@
|
||||
|
||||
set(FILES
|
||||
Source/ActorModule.cpp
|
||||
Source/Editor/EditorSystemComponent.h
|
||||
Source/Editor/EditorSystemComponent.cpp
|
||||
Tools/EMStudio/AtomRenderPlugin.h
|
||||
Tools/EMStudio/AtomRenderPlugin.cpp
|
||||
Tools/EMStudio/AnimViewportWidget.h
|
||||
Tools/EMStudio/AnimViewportWidget.cpp
|
||||
Tools/EMStudio/AnimViewportRenderer.h
|
||||
Tools/EMStudio/AnimViewportRenderer.cpp
|
||||
Tools/EMStudio/AnimViewportSettings.h
|
||||
Tools/EMStudio/AnimViewportSettings.cpp
|
||||
)
|
||||
|
||||
@@ -109,6 +109,8 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
AZ::AzToolsFramework
|
||||
Legacy::Editor.Headers
|
||||
3rdParty::OpenGLInterface
|
||||
Gem::AtomToolsFramework.Static
|
||||
Gem::AtomToolsFramework.Editor
|
||||
COMPILE_DEFINITIONS
|
||||
PUBLIC
|
||||
EMFX_EMSTUDIOLYEMBEDDED
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "CommandManager.h"
|
||||
#include <EMotionFX/Source/EMotionFXManager.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <Source/Integration/Assets/ActorAsset.h>
|
||||
|
||||
|
||||
namespace CommandSystem
|
||||
@@ -729,7 +730,8 @@ namespace CommandSystem
|
||||
m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag();
|
||||
|
||||
// get rid of the actor
|
||||
EMotionFX::GetActorManager().UnregisterActor(EMotionFX::GetActorManager().FindSharedActorByID(actor->GetID()));
|
||||
const AZ::Data::AssetId actorAssetId = EMotionFX::GetActorManager().FindAssetIdByActorId(actor->GetID());
|
||||
EMotionFX::GetActorManager().UnregisterActor(actorAssetId);
|
||||
|
||||
// mark the workspace as dirty
|
||||
GetCommandManager()->SetWorkspaceDirtyFlag(true);
|
||||
@@ -818,7 +820,6 @@ namespace CommandSystem
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// ignore visualization actor instances
|
||||
if (actorInstance->GetIsUsedForVisualization())
|
||||
{
|
||||
@@ -849,12 +850,6 @@ namespace CommandSystem
|
||||
// get the current actor
|
||||
EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i);
|
||||
|
||||
// ignore runtime-owned actors
|
||||
if (actor->GetIsOwnedByRuntime())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// ignore visualization actors
|
||||
if (actor->GetIsUsedForVisualization())
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h>
|
||||
#include "CommandManager.h"
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <Source/Integration/Assets/ActorAsset.h>
|
||||
|
||||
|
||||
namespace CommandSystem
|
||||
@@ -65,35 +66,29 @@ namespace CommandSystem
|
||||
filename = EMotionFX::EMotionFXManager::ResolvePath(filename.c_str());
|
||||
}
|
||||
|
||||
// check if we have already loaded the actor
|
||||
EMotionFX::Actor* actorFromManager = EMotionFX::GetActorManager().FindActorByFileName(filename.c_str());
|
||||
if (actorFromManager)
|
||||
AZ::Data::AssetId actorAssetId;
|
||||
EBUS_EVENT_RESULT(
|
||||
actorAssetId, AZ::Data::AssetCatalogRequestBus, GetAssetIdByPath, filename.c_str(), AZ::Data::s_invalidAssetType, false);
|
||||
if (!actorAssetId.IsValid())
|
||||
{
|
||||
AZStd::to_string(outResult, actorFromManager->GetID());
|
||||
return true;
|
||||
}
|
||||
|
||||
// init the settings
|
||||
EMotionFX::Importer::ActorSettings settings;
|
||||
|
||||
// extract default values from the command syntax automatically, if they aren't specified explicitly
|
||||
settings.m_loadLimits = parameters.GetValueAsBool("loadLimits", this);
|
||||
settings.m_loadMorphTargets = parameters.GetValueAsBool("loadMorphTargets", this);
|
||||
settings.m_loadSkeletalLoDs = parameters.GetValueAsBool("loadSkeletalLODs", this);
|
||||
settings.m_dualQuatSkinning = parameters.GetValueAsBool("dualQuatSkinning", this);
|
||||
|
||||
// try to load the actor
|
||||
AZStd::shared_ptr<EMotionFX::Actor> actor {EMotionFX::GetImporter().LoadActor(filename.c_str(), &settings)};
|
||||
if (!actor)
|
||||
{
|
||||
outResult = AZStd::string::format("Failed to load actor from '%s'. File may not exist at this path or may have incorrect permissions", filename.c_str());
|
||||
outResult = AZStd::string::format("Cannot import actor. Cannot find asset at path %s.", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Because the actor is directly loaded from disk (without going through an actor asset), we need to ask for a blocking
|
||||
// load for the asset that actor is depend on.
|
||||
actor->Finalize(EMotionFX::Actor::LoadRequirement::RequireBlockingLoad);
|
||||
// check if we have already loaded the actor
|
||||
const size_t actorIndex = EMotionFX::GetActorManager().FindActorIndex(actorAssetId);
|
||||
if (actorIndex != InvalidIndex)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Do a blocking load of the asset.
|
||||
AZ::Data::Asset<EMotionFX::Integration::ActorAsset> actorAsset =
|
||||
AZ::Data::AssetManager::Instance().GetAsset<EMotionFX::Integration::ActorAsset>(
|
||||
actorAssetId, AZ::Data::AssetLoadBehavior::Default);
|
||||
actorAsset.BlockUntilLoadComplete();
|
||||
|
||||
EMotionFX::Actor* actor = actorAsset->GetActor();
|
||||
// set the actor id in case we have specified it as parameter
|
||||
if (actorID != MCORE_INVALIDINDEX32)
|
||||
{
|
||||
@@ -113,7 +108,6 @@ namespace CommandSystem
|
||||
GetCommandManager()->ExecuteCommandInsideCommand(AZStd::string::format("Select -actorID %i", actor->GetID()).c_str(), outResult);
|
||||
}
|
||||
|
||||
|
||||
// mark the workspace as dirty
|
||||
m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag();
|
||||
GetCommandManager()->SetWorkspaceDirtyFlag(true);
|
||||
@@ -121,7 +115,8 @@ namespace CommandSystem
|
||||
// return the id of the newly created actor
|
||||
AZStd::to_string(outResult, actor->GetID());
|
||||
|
||||
EMotionFX::GetActorManager().RegisterActor(AZStd::move(actor));
|
||||
// Register actor asset.
|
||||
EMotionFX::GetActorManager().RegisterActor(AZStd::move(actorAsset));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -145,14 +140,14 @@ namespace CommandSystem
|
||||
}
|
||||
|
||||
// find the actor based on the given id
|
||||
AZStd::shared_ptr<EMotionFX::Actor> actor = EMotionFX::GetActorManager().FindSharedActorByID(actorID);
|
||||
if (actor == nullptr)
|
||||
AZ::Data::AssetId actorAssetId = EMotionFX::GetActorManager().FindAssetIdByActorId(actorID);
|
||||
if (!actorAssetId.IsValid())
|
||||
{
|
||||
outResult = AZStd::string::format("Cannot remove actor. Actor ID %i is not valid.", actorID);
|
||||
return false;
|
||||
}
|
||||
|
||||
EMotionFX::GetActorManager().UnregisterActor(actor);
|
||||
EMotionFX::GetActorManager().UnregisterActor(actorAssetId);
|
||||
|
||||
// update our render actors
|
||||
AZStd::string updateRenderActorsResult;
|
||||
|
||||
@@ -183,11 +183,6 @@ namespace CommandSystem
|
||||
for (size_t i = 0; i < numActors; ++i)
|
||||
{
|
||||
EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i);
|
||||
|
||||
if (actor->GetIsOwnedByRuntime())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unselect == false)
|
||||
{
|
||||
@@ -211,11 +206,6 @@ namespace CommandSystem
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actor->GetIsOwnedByRuntime())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unselect == false)
|
||||
{
|
||||
selection.AddActor(actor);
|
||||
@@ -244,11 +234,6 @@ namespace CommandSystem
|
||||
{
|
||||
EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i);
|
||||
|
||||
if (actor->GetIsOwnedByRuntime())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AzFramework::StringFunc::Equal(valueString.c_str(), actor->GetName(), false /* no case */))
|
||||
{
|
||||
if (unselect == false)
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
#include <EMotionFX/Source/Actor.h>
|
||||
#include <EMotionFX/Source/AutoRegisteredActor.h>
|
||||
#include <EMotionFX/Source/Importer/Importer.h>
|
||||
#include <EMotionFX/CommandSystem/Source/MetaData.h>
|
||||
#include <EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/optional.h>
|
||||
#include <EMotionFX/Source/AutoRegisteredActor.h>
|
||||
#include <SceneAPI/SceneCore/Components/ExportingComponent.h>
|
||||
#include <SceneAPI/SceneCore/Events/ExportProductList.h>
|
||||
#include <Integration/System/SystemCommon.h>
|
||||
@@ -44,7 +43,7 @@ namespace EMotionFX
|
||||
static AZStd::optional<AZ::SceneAPI::Events::ExportProduct> GetFirstProductByType(
|
||||
const ActorGroupExportContext& context, AZ::Data::AssetType type);
|
||||
|
||||
AutoRegisteredActor m_actor;
|
||||
AZStd::shared_ptr<Actor> m_actor;
|
||||
AZStd::vector<AZStd::string> m_actorMaterialReferences;
|
||||
};
|
||||
} // namespace Pipeline
|
||||
|
||||
@@ -91,9 +91,6 @@ namespace EMotionFX
|
||||
m_simulatedObjectSetup = AZStd::make_shared<SimulatedObjectSetup>(this);
|
||||
|
||||
m_optimizeSkeleton = false;
|
||||
#if defined(EMFX_DEVELOPMENT_BUILD)
|
||||
m_isOwnedByRuntime = false;
|
||||
#endif // EMFX_DEVELOPMENT_BUILD
|
||||
|
||||
// make sure we have at least allocated the first LOD of materials and facial setups
|
||||
m_materials.reserve(4); // reserve space for 4 lods
|
||||
@@ -2074,25 +2071,6 @@ namespace EMotionFX
|
||||
return m_usedForVisualization;
|
||||
}
|
||||
|
||||
void Actor::SetIsOwnedByRuntime(bool isOwnedByRuntime)
|
||||
{
|
||||
#if defined(EMFX_DEVELOPMENT_BUILD)
|
||||
m_isOwnedByRuntime = isOwnedByRuntime;
|
||||
#else
|
||||
AZ_UNUSED(isOwnedByRuntime);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool Actor::GetIsOwnedByRuntime() const
|
||||
{
|
||||
#if defined(EMFX_DEVELOPMENT_BUILD)
|
||||
return m_isOwnedByRuntime;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
const AZ::Aabb& Actor::GetStaticAabb() const
|
||||
{
|
||||
return m_staticAabb;
|
||||
|
||||
@@ -720,12 +720,6 @@ namespace EMotionFX
|
||||
void SetIsUsedForVisualization(bool flag);
|
||||
bool GetIsUsedForVisualization() const;
|
||||
|
||||
/**
|
||||
* Marks the actor as used by the engine runtime, as opposed to the tool suite.
|
||||
*/
|
||||
void SetIsOwnedByRuntime(bool isOwnedByRuntime);
|
||||
bool GetIsOwnedByRuntime() const;
|
||||
|
||||
/**
|
||||
* Recursively find the parent bone that is enabled in a given LOD, starting from a given node.
|
||||
* For example if you have a finger bone, while the finger bones are disabled in the skeletal LOD, this function will return the index to the hand bone.
|
||||
@@ -940,8 +934,5 @@ namespace EMotionFX
|
||||
bool m_usedForVisualization; /**< Indicates if the actor is used for visualization specific things and is not used as a normal in-game actor. */
|
||||
bool m_optimizeSkeleton; /**< Indicates if we should perform/ */
|
||||
bool m_isReady = false; /**< If actor as well as its dependent files are fully loaded and initialized.*/
|
||||
#if defined(EMFX_DEVELOPMENT_BUILD)
|
||||
bool m_isOwnedByRuntime; /**< Set if the actor is used/owned by the engine runtime. */
|
||||
#endif // EMFX_DEVELOPMENT_BUILD
|
||||
};
|
||||
} // namespace EMotionFX
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace EMotionFX
|
||||
SetScheduler(MultiThreadScheduler::Create());
|
||||
|
||||
// reserve memory
|
||||
m_actors.reserve(512);
|
||||
m_actorInstances.reserve(1024);
|
||||
m_rootActorInstances.reserve(1024);
|
||||
}
|
||||
@@ -111,20 +110,23 @@ namespace EMotionFX
|
||||
|
||||
|
||||
// register the actor
|
||||
void ActorManager::RegisterActor(AZStd::shared_ptr<Actor> actor)
|
||||
void ActorManager::RegisterActor(ActorAssetData actorAsset)
|
||||
{
|
||||
LockActors();
|
||||
|
||||
// check if we already registered
|
||||
if (FindActorIndex(actor.get()) != InvalidIndex)
|
||||
if (FindActorIndex(actorAsset.GetId()) != InvalidIndex)
|
||||
{
|
||||
MCore::LogWarning("EMotionFX::ActorManager::RegisterActor() - The actor at location 0x%x has already been registered as actor, most likely already by the LoadActor of the importer.", actor.get());
|
||||
MCore::LogWarning(
|
||||
"EMotionFX::ActorManager::RegisterActor() - The actor %s has already been registered as actor, most likely "
|
||||
"already by the LoadActor of the importer.",
|
||||
actorAsset->GetActor()->GetName());
|
||||
UnlockActors();
|
||||
return;
|
||||
}
|
||||
|
||||
// register it
|
||||
m_actors.emplace_back(AZStd::move(actor));
|
||||
m_actorAssets.emplace_back(AZStd::move(actorAsset));
|
||||
|
||||
UnlockActors();
|
||||
}
|
||||
@@ -146,60 +148,82 @@ namespace EMotionFX
|
||||
Actor* ActorManager::FindActorByName(const char* actorName) const
|
||||
{
|
||||
// get the number of actors and iterate through them
|
||||
const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [actorName](const AZStd::shared_ptr<Actor>& a)
|
||||
const auto found = AZStd::find_if(
|
||||
m_actorAssets.begin(), m_actorAssets.end(),
|
||||
[actorName](const ActorAssetData& a)
|
||||
{
|
||||
return a->GetNameString() == actorName;
|
||||
return a->GetActor()->GetNameString() == actorName;
|
||||
});
|
||||
|
||||
return (found != m_actors.end()) ? found->get() : nullptr;
|
||||
return (found != m_actorAssets.end()) ? (*found)->GetActor() : nullptr;
|
||||
}
|
||||
|
||||
|
||||
// find the actor for a given filename
|
||||
Actor* ActorManager::FindActorByFileName(const char* fileName) const
|
||||
{
|
||||
const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [fileName](const AZStd::shared_ptr<Actor>& a)
|
||||
const auto found = AZStd::find_if(
|
||||
m_actorAssets.begin(), m_actorAssets.end(),
|
||||
[fileName](const ActorAssetData& a)
|
||||
{
|
||||
return AzFramework::StringFunc::Equal(a->GetFileNameString().c_str(), fileName, false /* no case */);
|
||||
return AzFramework::StringFunc::Equal(
|
||||
a->GetActor()->GetFileNameString().c_str(), fileName, false /* no case */);
|
||||
});
|
||||
|
||||
return (found != m_actors.end()) ? found->get() : nullptr;
|
||||
return (found != m_actorAssets.end()) ? (*found)->GetActor() : nullptr;
|
||||
}
|
||||
|
||||
|
||||
// find the leader actor record for a given actor
|
||||
size_t ActorManager::FindActorIndex(Actor* actor) const
|
||||
size_t ActorManager::FindActorIndex(AZ::Data::AssetId assetId) const
|
||||
{
|
||||
const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [actor](const AZStd::shared_ptr<Actor>& a)
|
||||
const auto found = AZStd::find_if(
|
||||
m_actorAssets.begin(), m_actorAssets.end(),
|
||||
[assetId](const ActorAssetData& a)
|
||||
{
|
||||
return a.get() == actor;
|
||||
return a.GetId() == assetId;
|
||||
});
|
||||
|
||||
return (found != m_actors.end()) ? AZStd::distance(m_actors.begin(), found) : InvalidIndex;
|
||||
return (found != m_actorAssets.end()) ? AZStd::distance(m_actorAssets.begin(), found) : InvalidIndex;
|
||||
}
|
||||
|
||||
size_t ActorManager::FindActorIndex(const Actor* actor) const
|
||||
{
|
||||
const auto found = AZStd::find_if(
|
||||
m_actorAssets.begin(), m_actorAssets.end(),
|
||||
[actor](const ActorAssetData& a)
|
||||
{
|
||||
return a->GetActor() == actor;
|
||||
});
|
||||
|
||||
return (found != m_actorAssets.end()) ? AZStd::distance(m_actorAssets.begin(), found) : InvalidIndex;
|
||||
}
|
||||
|
||||
// find the actor for a given actor name
|
||||
size_t ActorManager::FindActorIndexByName(const char* actorName) const
|
||||
{
|
||||
const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [actorName](const AZStd::shared_ptr<Actor>& a)
|
||||
const auto found = AZStd::find_if(
|
||||
m_actorAssets.begin(), m_actorAssets.end(),
|
||||
[actorName](const ActorAssetData& a)
|
||||
{
|
||||
return a->GetNameString() == actorName;
|
||||
return a->GetActor()->GetNameString() == actorName;
|
||||
});
|
||||
|
||||
return (found != m_actors.end()) ? AZStd::distance(m_actors.begin(), found) : InvalidIndex;
|
||||
return (found != m_actorAssets.end()) ? AZStd::distance(m_actorAssets.begin(), found) : InvalidIndex;
|
||||
}
|
||||
|
||||
|
||||
// find the actor for a given actor filename
|
||||
size_t ActorManager::FindActorIndexByFileName(const char* filename) const
|
||||
{
|
||||
const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [filename](const AZStd::shared_ptr<Actor>& a)
|
||||
const auto found = AZStd::find_if(
|
||||
m_actorAssets.begin(), m_actorAssets.end(),
|
||||
[filename](const ActorAssetData& a)
|
||||
{
|
||||
return a->GetFileNameString() == filename;
|
||||
return a->GetActor()->GetFileNameString() == filename;
|
||||
});
|
||||
|
||||
return (found != m_actors.end()) ? AZStd::distance(m_actors.begin(), found) : InvalidIndex;
|
||||
return (found != m_actorAssets.end()) ? AZStd::distance(m_actorAssets.begin(), found) : InvalidIndex;
|
||||
}
|
||||
|
||||
|
||||
@@ -237,22 +261,26 @@ namespace EMotionFX
|
||||
// find the actor by the identification number
|
||||
Actor* ActorManager::FindActorByID(uint32 id) const
|
||||
{
|
||||
const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [id](const AZStd::shared_ptr<Actor>& a)
|
||||
const auto found = AZStd::find_if(
|
||||
m_actorAssets.begin(), m_actorAssets.end(),
|
||||
[id](const ActorAssetData& a)
|
||||
{
|
||||
return a->GetID() == id;
|
||||
return a->GetActor()->GetID() == id;
|
||||
});
|
||||
|
||||
return (found != m_actors.end()) ? found->get() : nullptr;
|
||||
return (found != m_actorAssets.end()) ? (*found)->GetActor() : nullptr;
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<Actor> ActorManager::FindSharedActorByID(uint32 id) const
|
||||
AZ::Data::AssetId ActorManager::FindAssetIdByActorId(uint32 id) const
|
||||
{
|
||||
const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [id](const AZStd::shared_ptr<Actor>& a)
|
||||
const auto found = AZStd::find_if(
|
||||
m_actorAssets.begin(), m_actorAssets.end(),
|
||||
[id](const ActorAssetData& a)
|
||||
{
|
||||
return a->GetID() == id;
|
||||
return a->GetActor()->GetID() == id;
|
||||
});
|
||||
|
||||
return (found != m_actors.end()) ? *found : nullptr;
|
||||
return (found != m_actorAssets.end()) ? found->GetId() : AZ::Data::AssetId();
|
||||
}
|
||||
|
||||
|
||||
@@ -264,14 +292,20 @@ namespace EMotionFX
|
||||
|
||||
|
||||
// unregister an actor
|
||||
void ActorManager::UnregisterActor(const AZStd::shared_ptr<Actor>& actor)
|
||||
void ActorManager::UnregisterActor(AZ::Data::AssetId actorAssetID)
|
||||
{
|
||||
LockActors();
|
||||
auto result = AZStd::find(m_actors.begin(), m_actors.end(), actor);
|
||||
if (result != m_actors.end())
|
||||
const auto found = AZStd::find_if(
|
||||
m_actorAssets.begin(), m_actorAssets.end(),
|
||||
[actorAssetID](const ActorAssetData& a)
|
||||
{
|
||||
return a.GetId() == actorAssetID;
|
||||
});
|
||||
if (found != m_actorAssets.end())
|
||||
{
|
||||
m_actors.erase(result);
|
||||
m_actorAssets.erase(found);
|
||||
}
|
||||
|
||||
UnlockActors();
|
||||
}
|
||||
|
||||
@@ -297,7 +331,7 @@ namespace EMotionFX
|
||||
LockActors();
|
||||
|
||||
// clear all actors
|
||||
m_actors.clear();
|
||||
m_actorAssets.clear();
|
||||
|
||||
// TODO: what if there are still references to the actors inside the list of registered actor instances?
|
||||
UnlockActors();
|
||||
@@ -390,7 +424,13 @@ namespace EMotionFX
|
||||
|
||||
Actor* ActorManager::GetActor(size_t nr) const
|
||||
{
|
||||
return m_actors[nr].get();
|
||||
return m_actorAssets[nr]->GetActor();
|
||||
}
|
||||
|
||||
|
||||
ActorAssetData ActorManager::GetActorAsset(size_t nr) const
|
||||
{
|
||||
return m_actorAssets[nr];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
#include <MCore/Source/MultiThreadManager.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/smart_ptr/weak_ptr.h>
|
||||
|
||||
#include <Source/Integration/Assets/ActorAsset.h>
|
||||
#include <Source/Integration/System/SystemCommon.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
@@ -47,7 +48,7 @@ namespace EMotionFX
|
||||
* Register an actor.
|
||||
* @param actor The actor to register.
|
||||
*/
|
||||
void RegisterActor(AZStd::shared_ptr<Actor> actor);
|
||||
void RegisterActor(ActorAssetData actorAsset);
|
||||
|
||||
/**
|
||||
* Unregister all actors.
|
||||
@@ -60,14 +61,14 @@ namespace EMotionFX
|
||||
* Unregister a specific actor.
|
||||
* @param actor The actor you passed to the RegisterActor function sometime before.
|
||||
*/
|
||||
void UnregisterActor(const AZStd::shared_ptr<Actor>& actor);
|
||||
void UnregisterActor(AZ::Data::AssetId actorAssetID);
|
||||
|
||||
/**
|
||||
* Get the number of registered actors.
|
||||
* This does not include the clones that have been optionally created.
|
||||
* @result The number of registered actors.
|
||||
*/
|
||||
MCORE_INLINE size_t GetNumActors() const { return m_actors.size(); }
|
||||
MCORE_INLINE size_t GetNumActors() const { return m_actorAssets.size(); }
|
||||
|
||||
/**
|
||||
* Get a given actor.
|
||||
@@ -78,6 +79,7 @@ namespace EMotionFX
|
||||
* @result A reference to the actor object that contains the array of Actor objects.
|
||||
*/
|
||||
Actor* GetActor(size_t nr) const;
|
||||
ActorAssetData GetActorAsset(size_t nr) const;
|
||||
|
||||
/**
|
||||
* Find the given actor by name.
|
||||
@@ -99,7 +101,8 @@ namespace EMotionFX
|
||||
* @param actor The actor object you once passed to RegisterActor.
|
||||
* @result Returns the actor number, which is in range of [0..GetNumActors()-1], or returns MCORE_INVALIDINDEX32 when not found.
|
||||
*/
|
||||
size_t FindActorIndex(Actor* actor) const;
|
||||
size_t FindActorIndex(AZ::Data::AssetId assetId) const;
|
||||
size_t FindActorIndex(const Actor* actor) const;
|
||||
|
||||
/**
|
||||
* Find the actor number for a given actor name.
|
||||
@@ -160,7 +163,7 @@ namespace EMotionFX
|
||||
*/
|
||||
Actor* FindActorByID(uint32 id) const;
|
||||
|
||||
AZStd::shared_ptr<Actor> FindSharedActorByID(uint32 id) const;
|
||||
AZ::Data::AssetId FindAssetIdByActorId(uint32 id) const;
|
||||
|
||||
/**
|
||||
* Check if the given actor instance is registered.
|
||||
@@ -255,9 +258,9 @@ namespace EMotionFX
|
||||
void UnlockActors();
|
||||
|
||||
private:
|
||||
AZStd::vector<ActorInstance*> m_actorInstances; /**< The registered actor instances. */
|
||||
AZStd::vector<AZStd::shared_ptr<Actor>> m_actors; /**< The registered actors. */
|
||||
AZStd::vector<ActorInstance*> m_rootActorInstances; /**< Root actor instances (roots of all attachment chains). */
|
||||
AZStd::vector<ActorInstance*> m_actorInstances; /**< The registered actor instances. */
|
||||
AZStd::vector<ActorAssetData> m_actorAssets;
|
||||
AZStd::vector<ActorInstance*> m_rootActorInstances; /**< Root actor instances (roots of all attachment chains). */
|
||||
ActorUpdateScheduler* m_scheduler; /**< The update scheduler to use. */
|
||||
MCore::MutexRecursive m_actorLock; /**< The multithread lock for touching the actors array. */
|
||||
MCore::MutexRecursive m_actorInstanceLock; /**< The multithread lock for touching the actor instances array. */
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
#include <EMotionFX/Source/EMotionFXManager.h>
|
||||
#include <EMotionFX/Source/ActorManager.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
class Actor;
|
||||
|
||||
/**
|
||||
* @brief An Actor pointer that unregisters itself when it goes out of
|
||||
* scope
|
||||
*
|
||||
* This class allows for simple functionality of automatically registering
|
||||
* and unregistering an actor from the manager. Its primary use case is the
|
||||
* ActorAsset, that shares ownership with the manager. But it can also be
|
||||
* used anywhere that needs to make an Actor that needs to be in the
|
||||
* Manager for a given period of time. A good example of this is anything
|
||||
* that needs Actor commands to work on an actor that is made in a given
|
||||
* scope. One main place where this happens is in the Actor asset processor
|
||||
* code.
|
||||
*/
|
||||
class AutoRegisteredActor
|
||||
{
|
||||
public:
|
||||
AutoRegisteredActor() = default;
|
||||
|
||||
template<class T>
|
||||
AutoRegisteredActor(AZStd::shared_ptr<T> actor)
|
||||
: m_actor(AZStd::move(actor))
|
||||
{
|
||||
Register(m_actor);
|
||||
}
|
||||
template<class T>
|
||||
AutoRegisteredActor(AZStd::unique_ptr<T> actor)
|
||||
: m_actor(AZStd::move(actor))
|
||||
{
|
||||
Register(m_actor);
|
||||
}
|
||||
|
||||
// This class is not copyable, because a given actor cannot be
|
||||
// registered with the manager multiple times
|
||||
AutoRegisteredActor(const AutoRegisteredActor&) = delete;
|
||||
AutoRegisteredActor& operator=(const AutoRegisteredActor&) = delete;
|
||||
|
||||
AutoRegisteredActor(AutoRegisteredActor&& other) noexcept
|
||||
{
|
||||
*this = AZStd::move(other);
|
||||
}
|
||||
|
||||
AutoRegisteredActor& operator=(AutoRegisteredActor&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
Unregister(m_actor);
|
||||
m_actor = AZStd::move(other.m_actor);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~AutoRegisteredActor()
|
||||
{
|
||||
Unregister(m_actor);
|
||||
}
|
||||
|
||||
Actor* operator->() const
|
||||
{
|
||||
return m_actor.operator->();
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return static_cast<bool>(m_actor);
|
||||
}
|
||||
|
||||
Actor* get() const
|
||||
{
|
||||
return m_actor.get();
|
||||
}
|
||||
|
||||
private:
|
||||
void Register(const AZStd::shared_ptr<Actor>& actor)
|
||||
{
|
||||
if (actor)
|
||||
{
|
||||
GetActorManager().RegisterActor(actor);
|
||||
}
|
||||
}
|
||||
|
||||
void Unregister(const AZStd::shared_ptr<Actor>& actor)
|
||||
{
|
||||
if (actor)
|
||||
{
|
||||
GetActorManager().UnregisterActor(actor);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<Actor> m_actor;
|
||||
};
|
||||
} // namespace EMotionFX
|
||||
+50
-28
@@ -46,15 +46,10 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace EMStudio
|
||||
{
|
||||
//--------------------------------------------------------------------------
|
||||
// globals
|
||||
//--------------------------------------------------------------------------
|
||||
EMStudioManager* gEMStudioMgr = nullptr;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// class EMStudioManager
|
||||
//--------------------------------------------------------------------------
|
||||
AZ_CLASS_ALLOCATOR_IMPL(EMStudioManager, AZ::SystemAllocator, 0)
|
||||
|
||||
// constructor
|
||||
EMStudioManager::EMStudioManager(QApplication* app, [[maybe_unused]] int& argc, [[maybe_unused]] char* argv[])
|
||||
@@ -105,8 +100,9 @@ namespace EMStudio
|
||||
|
||||
// log some information
|
||||
LogInfo();
|
||||
}
|
||||
|
||||
AZ::Interface<EMStudioManager>::Register(this);
|
||||
}
|
||||
|
||||
// destructor
|
||||
EMStudioManager::~EMStudioManager()
|
||||
@@ -130,6 +126,8 @@ namespace EMStudio
|
||||
delete m_commandManager;
|
||||
|
||||
AZ::AllocatorInstance<UIAllocator>::Destroy();
|
||||
|
||||
AZ::Interface<EMStudioManager>::Unregister(this);
|
||||
}
|
||||
|
||||
MainWindow* EMStudioManager::GetMainWindow()
|
||||
@@ -422,6 +420,12 @@ namespace EMStudio
|
||||
}
|
||||
|
||||
|
||||
EMStudioManager* EMStudioManager::GetInstance()
|
||||
{
|
||||
return AZ::Interface<EMStudioManager>().Get();
|
||||
}
|
||||
|
||||
|
||||
// function to add a gizmo to the manager
|
||||
MCommon::TransformationManipulator* EMStudioManager::AddTransformationManipulator(MCommon::TransformationManipulator* manipulator)
|
||||
{
|
||||
@@ -494,30 +498,48 @@ namespace EMStudio
|
||||
painter.drawPath(path);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// class Initializer
|
||||
//--------------------------------------------------------------------------
|
||||
// initialize EMotion Studio
|
||||
bool Initializer::Init(QApplication* app, int& argc, char* argv[])
|
||||
// shortcuts
|
||||
QApplication* GetApp()
|
||||
{
|
||||
// do nothing if we already have initialized
|
||||
if (gEMStudioMgr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// create the new EMStudio object
|
||||
gEMStudioMgr = new EMStudioManager(app, argc, argv);
|
||||
|
||||
// return success
|
||||
return true;
|
||||
return EMStudioManager::GetInstance()->GetApp();
|
||||
}
|
||||
EMStudioManager* GetManager()
|
||||
{
|
||||
return EMStudioManager::GetInstance();
|
||||
}
|
||||
|
||||
|
||||
// the shutdown function
|
||||
void Initializer::Shutdown()
|
||||
bool HasMainWindow()
|
||||
{
|
||||
delete gEMStudioMgr;
|
||||
gEMStudioMgr = nullptr;
|
||||
return EMStudioManager::GetInstance()->HasMainWindow();
|
||||
}
|
||||
|
||||
MainWindow* GetMainWindow()
|
||||
{
|
||||
return EMStudioManager::GetInstance()->GetMainWindow();
|
||||
}
|
||||
|
||||
PluginManager* GetPluginManager()
|
||||
{
|
||||
return EMStudioManager::GetInstance()->GetPluginManager();
|
||||
}
|
||||
|
||||
LayoutManager* GetLayoutManager()
|
||||
{
|
||||
return EMStudioManager::GetInstance()->GetLayoutManager();
|
||||
}
|
||||
|
||||
NotificationWindowManager* GetNotificationWindowManager()
|
||||
{
|
||||
return EMStudioManager::GetInstance()->GetNotificationWindowManager();
|
||||
}
|
||||
|
||||
MotionEventPresetManager* GetEventPresetManager()
|
||||
{
|
||||
return EMStudioManager::GetInstance()->GetEventPresetManger();
|
||||
}
|
||||
|
||||
CommandSystem::CommandManager* GetCommandManager()
|
||||
{
|
||||
return EMStudioManager::GetInstance()->GetCommandManager();
|
||||
}
|
||||
} // namespace EMStudio
|
||||
|
||||
+17
-30
@@ -53,9 +53,10 @@ namespace EMStudio
|
||||
class EMSTUDIO_API EMStudioManager
|
||||
: private EMotionFX::SkeletonOutlinerNotificationBus::Handler
|
||||
{
|
||||
MCORE_MEMORYOBJECTCATEGORY(EMStudioManager, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_EMSTUDIOSDK)
|
||||
|
||||
public:
|
||||
AZ_RTTI(EMStudio::EMStudioManager, "{D45E95CF-0C7B-44F1-A9D4-99A1E12A5AB5}")
|
||||
AZ_CLASS_ALLOCATOR_DECL
|
||||
|
||||
EMStudioManager(QApplication* app, int& argc, char* argv[]);
|
||||
~EMStudioManager();
|
||||
|
||||
@@ -72,6 +73,9 @@ namespace EMStudio
|
||||
AZStd::string GetRecoverFolder() const;
|
||||
AZStd::string GetAutosavesFolder() const;
|
||||
|
||||
// Singleton pattern
|
||||
static EMStudioManager* GetInstance();
|
||||
|
||||
// text rendering helper function
|
||||
static void RenderText(QPainter& painter, const QString& text, const QColor& textColor, const QFont& font, const QFontMetrics& fontMetrics, Qt::Alignment textAlignment, const QRect& rect);
|
||||
|
||||
@@ -150,34 +154,17 @@ namespace EMStudio
|
||||
void OnRemoveCommand(size_t historyIndex) override { MCORE_UNUSED(historyIndex); }
|
||||
void OnSetCurrentCommand(size_t index) override { MCORE_UNUSED(index); }
|
||||
};
|
||||
EventProcessingCallback* m_eventProcessingCallback;
|
||||
EventProcessingCallback* m_eventProcessingCallback = nullptr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
class EMSTUDIO_API Initializer
|
||||
{
|
||||
public:
|
||||
static bool MCORE_CDECL Init(QApplication* app, int& argc, char* argv[]);
|
||||
static void MCORE_CDECL Shutdown();
|
||||
};
|
||||
|
||||
|
||||
// the global manager
|
||||
extern EMSTUDIO_API EMStudioManager* gEMStudioMgr;
|
||||
|
||||
// shortcuts
|
||||
MCORE_INLINE QApplication* GetApp() { return gEMStudioMgr->GetApp(); }
|
||||
MCORE_INLINE EMStudioManager* GetManager() { return gEMStudioMgr; }
|
||||
MCORE_INLINE bool HasMainWindow() { return gEMStudioMgr->HasMainWindow(); }
|
||||
MCORE_INLINE MainWindow* GetMainWindow() { return gEMStudioMgr->GetMainWindow(); }
|
||||
MCORE_INLINE PluginManager* GetPluginManager() { return gEMStudioMgr->GetPluginManager(); }
|
||||
MCORE_INLINE LayoutManager* GetLayoutManager() { return gEMStudioMgr->GetLayoutManager(); }
|
||||
MCORE_INLINE NotificationWindowManager* GetNotificationWindowManager() { return gEMStudioMgr->GetNotificationWindowManager(); }
|
||||
MCORE_INLINE MotionEventPresetManager* GetEventPresetManager() { return gEMStudioMgr->GetEventPresetManger(); }
|
||||
MCORE_INLINE CommandSystem::CommandManager* GetCommandManager() { return gEMStudioMgr->GetCommandManager(); }
|
||||
// Shortcuts
|
||||
QApplication* GetApp();
|
||||
EMStudioManager* GetManager();
|
||||
bool HasMainWindow();
|
||||
MainWindow* GetMainWindow();
|
||||
PluginManager* GetPluginManager();
|
||||
LayoutManager* GetLayoutManager();
|
||||
NotificationWindowManager* GetNotificationWindowManager();
|
||||
MotionEventPresetManager* GetEventPresetManager();
|
||||
CommandSystem::CommandManager* GetCommandManager();
|
||||
} // namespace EMStudio
|
||||
|
||||
@@ -112,10 +112,6 @@ namespace EMStudio
|
||||
for (size_t i = 0; i < actorCount; ++i)
|
||||
{
|
||||
EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i);
|
||||
if (actor->GetIsOwnedByRuntime())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AzFramework::StringFunc::Equal(filename, actor->GetFileName()))
|
||||
{
|
||||
|
||||
@@ -1792,11 +1792,6 @@ namespace EMStudio
|
||||
{
|
||||
EMotionFX::Actor* actor = selectionList.GetActorInstance(i)->GetActor();
|
||||
|
||||
if (actor->GetIsOwnedByRuntime())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AZStd::find(savingActors.begin(), savingActors.end(), actor) == savingActors.end())
|
||||
{
|
||||
savingActors.push_back(actor);
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <EMotionStudio/EMStudioSDK/Source/EMStudioConfig.h>
|
||||
#include <EMotionStudio/EMStudioSDK/Source/GUIOptions.h>
|
||||
#include <EMotionStudio/EMStudioSDK/Source/PluginOptionsBus.h>
|
||||
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioConfig.h>
|
||||
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/GUIOptions.h>
|
||||
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginOptionsBus.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <MCore/Source/Command.h>
|
||||
#include <MCore/Source/StandardHeaders.h>
|
||||
|
||||
+2
-2
@@ -389,7 +389,7 @@ namespace EMStudio
|
||||
// get the current actor and the number of clones
|
||||
EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i);
|
||||
|
||||
if (actor->GetIsOwnedByRuntime() || !actor->IsReady())
|
||||
if (!actor->IsReady())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -421,7 +421,7 @@ namespace EMStudio
|
||||
|
||||
// At this point the render actor could point to an already deleted actor.
|
||||
// In case the actor got deleted we might get an unexpected flag as result.
|
||||
if (!found || (found && actor->GetIsOwnedByRuntime()) || (!actor->IsReady()))
|
||||
if (!found || (!actor->IsReady()))
|
||||
{
|
||||
DestroyEMStudioActor(actor);
|
||||
}
|
||||
|
||||
+2
-2
@@ -155,12 +155,12 @@ namespace EMStudio
|
||||
cameraMenu->addAction("Reset Camera", [this]() { this->OnResetCamera(); });
|
||||
|
||||
QAction* showSelectedAction = cameraMenu->addAction("Show Selected", this, &RenderViewWidget::OnShowSelected);
|
||||
showSelectedAction->setShortcut(Qt::Key_S);
|
||||
showSelectedAction->setShortcut(QKeySequence(Qt::Key_S + Qt::SHIFT));
|
||||
GetMainWindow()->GetShortcutManager()->RegisterKeyboardShortcut(showSelectedAction, RenderPlugin::s_renderWindowShortcutGroupName, true);
|
||||
addAction(showSelectedAction);
|
||||
|
||||
QAction* showEntireSceneAction = cameraMenu->addAction("Show Entire Scene", this, &RenderViewWidget::OnShowEntireScene);
|
||||
showEntireSceneAction->setShortcut(Qt::Key_A);
|
||||
showEntireSceneAction->setShortcut(QKeySequence(Qt::Key_A + Qt::SHIFT));
|
||||
GetMainWindow()->GetShortcutManager()->RegisterKeyboardShortcut(showEntireSceneAction, RenderPlugin::s_renderWindowShortcutGroupName, true);
|
||||
addAction(showEntireSceneAction);
|
||||
|
||||
|
||||
+1
-2
@@ -65,8 +65,7 @@ namespace EMStudio
|
||||
|
||||
m_actorCheckbox = new QCheckBox("Actors");
|
||||
m_actorCheckbox->setObjectName("EMFX.ResetSettingsDialog.Actors");
|
||||
const bool hasActors = HasEntityInEditor(
|
||||
EMotionFX::GetActorManager(), &EMotionFX::ActorManager::GetNumActors, &EMotionFX::ActorManager::GetActor);
|
||||
const bool hasActors = EMotionFX::GetActorManager().GetNumActors() > 0;
|
||||
m_actorCheckbox->setChecked(hasActors);
|
||||
m_actorCheckbox->setDisabled(!hasActors);
|
||||
|
||||
|
||||
+10
-1
@@ -327,7 +327,16 @@ namespace EMStudio
|
||||
|
||||
void NodeWindowPlugin::OnActorReady([[maybe_unused]] EMotionFX::Actor* actor)
|
||||
{
|
||||
ReInit();
|
||||
m_reinitRequested = true;
|
||||
}
|
||||
|
||||
void NodeWindowPlugin::ProcessFrame([[maybe_unused]] float timePassedInSeconds)
|
||||
{
|
||||
if (m_reinitRequested)
|
||||
{
|
||||
ReInit();
|
||||
m_reinitRequested = false;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
|
||||
+5
@@ -60,6 +60,8 @@ namespace EMStudio
|
||||
EMStudioPlugin* Clone() override;
|
||||
void ReInit();
|
||||
|
||||
void ProcessFrame(float timePassedInSeconds) override;
|
||||
|
||||
public slots:
|
||||
void OnNodeChanged();
|
||||
void VisibilityChanged(bool isVisible);
|
||||
@@ -87,5 +89,8 @@ namespace EMStudio
|
||||
|
||||
AZStd::unique_ptr<ActorInfo> m_actorInfo;
|
||||
AZStd::unique_ptr<NodeInfo> m_nodeInfo;
|
||||
|
||||
// Use this flag to defer the reinit function to main thread.
|
||||
bool m_reinitRequested = false;
|
||||
};
|
||||
} // namespace EMStudio
|
||||
|
||||
-6
@@ -123,12 +123,6 @@ namespace EMStudio
|
||||
continue;
|
||||
}
|
||||
|
||||
// ignore engine actors
|
||||
if (actor->GetIsOwnedByRuntime())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// create a tree item for the new attachment
|
||||
QTreeWidgetItem* newItem = new QTreeWidgetItem(m_treeWidget);
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ set(FILES
|
||||
Source/AttachmentNode.h
|
||||
Source/AttachmentSkin.cpp
|
||||
Source/AttachmentSkin.h
|
||||
Source/AutoRegisteredActor.h
|
||||
Source/BaseObject.cpp
|
||||
Source/BaseObject.h
|
||||
Source/CompressedKeyFrames.h
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzFramework/Physics/AnimationConfiguration.h>
|
||||
#include <AzFramework/Physics/Character.h>
|
||||
|
||||
#include <Integration/Assets/ActorAsset.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
@@ -96,6 +96,9 @@ namespace EMotionFX
|
||||
/// Returns skinning method used by the actor.
|
||||
virtual SkinningMethod GetSkinningMethod() const = 0;
|
||||
|
||||
// Use this to alter the actor asset.
|
||||
virtual void SetActorAsset(AZ::Data::Asset<EMotionFX::Integration::ActorAsset> actorAsset) = 0;
|
||||
|
||||
static const size_t s_invalidJointIndex = std::numeric_limits<size_t>::max();
|
||||
};
|
||||
|
||||
|
||||
@@ -46,6 +46,9 @@ namespace EMotionFX
|
||||
public:
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
|
||||
// Use this bus to register custom EMotionFX plugin.
|
||||
virtual void OnRegisterPlugin() = 0;
|
||||
};
|
||||
using SystemNotificationBus = AZ::EBus<SystemNotifications>;
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <EMotionFX/Source/ActorManager.h>
|
||||
#include <EMotionFX/Source/ActorInstance.h>
|
||||
#include <EMotionFX/Source/EMotionFXManager.h>
|
||||
#include <EMotionFX/Source/Importer/Importer.h>
|
||||
@@ -64,8 +63,7 @@ namespace EMotionFX
|
||||
&actorSettings,
|
||||
"");
|
||||
|
||||
// Set the is owned by runtime flag before finalizing the actor, as that uses the flag already.
|
||||
assetData->m_emfxActor->SetIsOwnedByRuntime(true);
|
||||
assetData->m_emfxActor->SetFileName(asset.GetHint().c_str());
|
||||
assetData->m_emfxActor->Finalize();
|
||||
|
||||
// Clear out the EMFX raw asset data.
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <Integration/Assets/AssetCommon.h>
|
||||
#include <Integration/Rendering/RenderActor.h>
|
||||
#include <EMotionFX/Source/AutoRegisteredActor.h>
|
||||
|
||||
|
||||
namespace EMotionFX
|
||||
@@ -58,7 +57,7 @@ namespace EMotionFX
|
||||
void InitRenderActor();
|
||||
|
||||
private:
|
||||
AutoRegisteredActor m_emfxActor; ///< Pointer to shared EMotionFX actor
|
||||
AZStd::shared_ptr<Actor> m_emfxActor;
|
||||
AZStd::unique_ptr<RenderActor> m_renderActor;
|
||||
};
|
||||
|
||||
@@ -81,6 +80,8 @@ namespace EMotionFX
|
||||
const char* GetBrowserIcon() const override;
|
||||
};
|
||||
} // namespace Integration
|
||||
|
||||
using ActorAssetData = AZ::Data::Asset<Integration::ActorAsset>;
|
||||
} // namespace EMotionFX
|
||||
|
||||
namespace AZ
|
||||
|
||||
@@ -121,6 +121,7 @@ namespace EMotionFX
|
||||
void SetRenderCharacter(bool enable) override;
|
||||
bool GetRenderActorVisible() const override;
|
||||
SkinningMethod GetSkinningMethod() const override;
|
||||
void SetActorAsset(AZ::Data::Asset<ActorAsset> actorAsset) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ActorComponentNotificationBus::Handler
|
||||
@@ -178,8 +179,6 @@ namespace EMotionFX
|
||||
void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
|
||||
|
||||
bool IsPhysicsSceneSimulationFinishEventConnected() const;
|
||||
|
||||
void SetActorAsset(AZ::Data::Asset<ActorAsset> actorAsset);
|
||||
AZ::Data::Asset<ActorAsset> GetActorAsset() const { return m_configuration.m_actorAsset; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace EMotionFX
|
||||
bool GetRenderActorVisible() const override;
|
||||
size_t GetNumJoints() const override;
|
||||
SkinningMethod GetSkinningMethod() const override;
|
||||
void SetActorAsset(AZ::Data::Asset<ActorAsset> actorAsset) override;
|
||||
|
||||
// EditorActorComponentRequestBus overrides ...
|
||||
const AZ::Data::AssetId& GetActorAssetId() override;
|
||||
@@ -79,8 +80,6 @@ namespace EMotionFX
|
||||
void OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
|
||||
void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
|
||||
|
||||
void SetActorAsset(AZ::Data::Asset<ActorAsset> actorAsset);
|
||||
|
||||
// BoundsRequestBus overrides ...
|
||||
AZ::Aabb GetWorldBounds() override;
|
||||
AZ::Aabb GetLocalBounds() override;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <EMotionFX/Source/MotionEventTrack.h>
|
||||
#include <EMotionFX/Source/AnimGraphSyncTrack.h>
|
||||
#include <EMotionFX/Source/AnimGraph.h>
|
||||
#include <EMotionFX/Source/ActorManager.h>
|
||||
|
||||
#include <EMotionFX/Source/PhysicsSetup.h>
|
||||
#include <EMotionFX/Source/SimulatedObjectSetup.h>
|
||||
@@ -45,6 +46,7 @@
|
||||
#include <EMotionFX/Source/PoseData.h>
|
||||
#include <EMotionFX/Source/PoseDataRagdoll.h>
|
||||
|
||||
#include <Integration/AnimationBus.h>
|
||||
#include <Integration/EMotionFXBus.h>
|
||||
#include <Integration/Assets/ActorAsset.h>
|
||||
#include <Integration/Assets/MotionAsset.h>
|
||||
@@ -69,7 +71,6 @@
|
||||
# include <AzToolsFramework/API/ViewPaneOptions.h>
|
||||
# include <AzCore/std/string/wildcard.h>
|
||||
# include <QApplication>
|
||||
# include <EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
|
||||
# include <EMotionStudio/EMStudioSDK/Source/MainWindow.h>
|
||||
# include <EMotionStudio/EMStudioSDK/Source/PluginManager.h>
|
||||
// EMStudio plugins
|
||||
@@ -528,7 +529,7 @@ namespace EMotionFX
|
||||
|
||||
if (EMStudio::GetManager())
|
||||
{
|
||||
EMStudio::Initializer::Shutdown();
|
||||
m_emstudioManager.reset();
|
||||
MysticQt::Initializer::Shutdown();
|
||||
}
|
||||
|
||||
@@ -798,6 +799,8 @@ namespace EMotionFX
|
||||
pluginManager->RegisterPlugin(new EMotionFX::RagdollNodeInspectorPlugin());
|
||||
pluginManager->RegisterPlugin(new EMotionFX::ClothJointInspectorPlugin());
|
||||
pluginManager->RegisterPlugin(new EMotionFX::SimulatedObjectWidget());
|
||||
|
||||
SystemNotificationBus::Broadcast(&SystemNotificationBus::Events::OnRegisterPlugin);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -813,7 +816,7 @@ namespace EMotionFX
|
||||
char** argv = nullptr;
|
||||
|
||||
MysticQt::Initializer::Init("", editorAssetsPath.c_str());
|
||||
EMStudio::Initializer::Init(qApp, argc, argv);
|
||||
m_emstudioManager = AZStd::make_unique<EMStudio::EMStudioManager>(qApp, argc, argv);
|
||||
|
||||
InitializeEMStudioPlugins();
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
# include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
# include <AzToolsFramework/API/EditorAnimationSystemRequestBus.h>
|
||||
# include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
# include <EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
|
||||
#endif // EMOTIONFXANIMATION_EDITOR
|
||||
|
||||
namespace AZ
|
||||
@@ -126,6 +127,10 @@ namespace EMotionFX
|
||||
AZStd::vector<AZStd::unique_ptr<AZ::Data::AssetHandler> > m_assetHandlers;
|
||||
AZStd::unique_ptr<EMotionFXEventHandler> m_eventHandler;
|
||||
AZStd::unique_ptr<RenderBackendManager> m_renderBackendManager;
|
||||
|
||||
#if defined(EMOTIONFXANIMATION_EDITOR)
|
||||
AZStd::unique_ptr<EMStudio::EMStudioManager> m_emstudioManager;
|
||||
#endif // EMOTIONFXANIMATION_EDITOR
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,15 @@
|
||||
#include <MCore/Source/ReflectionSerializer.h>
|
||||
#include <EMotionFX/Source/Actor.h>
|
||||
#include <EMotionFX/Source/ActorInstance.h>
|
||||
#include <EMotionFX/Source/ActorManager.h>
|
||||
#include <EMotionFX/Source/Importer/Importer.h>
|
||||
#include <EMotionFX/Source/EMotionFXManager.h>
|
||||
#include <EMotionFX/Source/SimulatedObjectSetup.h>
|
||||
|
||||
#include <Tests/TestAssetCode/JackActor.h>
|
||||
#include <Tests/TestAssetCode/ActorFactory.h>
|
||||
#include <Tests/TestAssetCode/TestActorAssets.h>
|
||||
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
@@ -23,8 +26,9 @@ namespace EMotionFX
|
||||
{
|
||||
SystemComponentFixture::SetUp();
|
||||
|
||||
m_actor = ActorFactory::CreateAndInit<JackNoMeshesActor>();
|
||||
m_actorInstance = ActorInstance::Create(m_actor.get());
|
||||
AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}");
|
||||
m_actorAsset = TestActorAssets::CreateActorAssetAndRegister<JackNoMeshesActor>(actorAssetId);
|
||||
m_actorInstance = ActorInstance::Create(GetActor());
|
||||
}
|
||||
|
||||
void ActorFixture::TearDown()
|
||||
@@ -35,6 +39,7 @@ namespace EMotionFX
|
||||
m_actorInstance = nullptr;
|
||||
}
|
||||
|
||||
GetEMotionFX().GetActorManager()->UnregisterAllActors();
|
||||
SystemComponentFixture::TearDown();
|
||||
}
|
||||
|
||||
@@ -71,7 +76,7 @@ namespace EMotionFX
|
||||
|
||||
AZ::ObjectStream::FilterDescriptor loadFilter(nullptr, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES);
|
||||
SimulatedObjectSetup* setup = AZ::Utils::LoadObjectFromBuffer<EMotionFX::SimulatedObjectSetup>(data.data(), data.size(), serializeContext, loadFilter);
|
||||
setup->InitAfterLoad(m_actor.get());
|
||||
setup->InitAfterLoad(GetActor());
|
||||
return setup;
|
||||
}
|
||||
|
||||
@@ -80,4 +85,10 @@ namespace EMotionFX
|
||||
{
|
||||
return { "Bip01__pelvis", "l_upLeg", "l_loLeg", "l_ankle" };
|
||||
}
|
||||
|
||||
|
||||
Actor* ActorFixture::GetActor() const
|
||||
{
|
||||
return m_actorAsset->GetActor();
|
||||
}
|
||||
} // namespace EMotionFX
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "SystemComponentFixture.h"
|
||||
#include <EMotionFX/Source/AutoRegisteredActor.h>
|
||||
|
||||
#include <Integration/Assets/ActorAsset.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
@@ -31,7 +30,9 @@ namespace EMotionFX
|
||||
AZStd::vector<AZStd::string> GetTestJointNames() const;
|
||||
|
||||
protected:
|
||||
AutoRegisteredActor m_actor{};
|
||||
Actor* GetActor() const;
|
||||
|
||||
AZ::Data::Asset<Integration::ActorAsset> m_actorAsset;
|
||||
ActorInstance* m_actorInstance = nullptr;
|
||||
};
|
||||
} // namespace EMotionFX
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace EMotionFX
|
||||
public:
|
||||
void CreateSubMotionLikeBindPose(const std::string& name)
|
||||
{
|
||||
const Skeleton* skeleton = m_actor->GetSkeleton();
|
||||
const Skeleton* skeleton = GetActor()->GetSkeleton();
|
||||
size_t jointIndex = InvalidIndex;
|
||||
const Node* node = skeleton->FindNodeAndIndexByName(name.c_str(), jointIndex);
|
||||
ASSERT_NE(node, nullptr);
|
||||
@@ -40,7 +40,7 @@ namespace EMotionFX
|
||||
void CreateSubMotion(const std::string& name, const Transform& transform)
|
||||
{
|
||||
// Find and store the joint index.
|
||||
const Skeleton* skeleton = m_actor->GetSkeleton();
|
||||
const Skeleton* skeleton = GetActor()->GetSkeleton();
|
||||
size_t jointIndex = InvalidIndex;
|
||||
const Node* node = skeleton->FindNodeAndIndexByName(name.c_str(), jointIndex);
|
||||
ASSERT_NE(node, nullptr);
|
||||
@@ -55,7 +55,7 @@ namespace EMotionFX
|
||||
ActorFixture::SetUp();
|
||||
|
||||
// Get the joint that isn't in the motion data.
|
||||
Node* footNode = m_actor->GetSkeleton()->FindNodeAndIndexByName("l_ball", m_footIndex);
|
||||
Node* footNode = GetActor()->GetSkeleton()->FindNodeAndIndexByName("l_ball", m_footIndex);
|
||||
ASSERT_NE(footNode, nullptr);
|
||||
ASSERT_NE(m_footIndex, InvalidIndex32);
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace EMotionFX
|
||||
|
||||
TEST_F(MotionSamplingFixture, SampleAdditiveJoint)
|
||||
{
|
||||
const Skeleton* skeleton = m_actor->GetSkeleton();
|
||||
const Skeleton* skeleton = GetActor()->GetSkeleton();
|
||||
|
||||
// Sample the joints that exist in our actor skeleton as well as inside the motion data.
|
||||
const Pose* bindPose = m_actorInstance->GetTransformData()->GetBindPose();
|
||||
@@ -106,7 +106,7 @@ namespace EMotionFX
|
||||
{
|
||||
// Sample the motion.
|
||||
Transform transform = Transform::CreateZero(); // Set all to Zero, not identity as this methods might return identity and we want to verify that.
|
||||
m_motion->CalcNodeTransform(m_motionInstance, &transform, m_actor.get(), skeleton->GetNode(jointIndex), /*timeValue=*/0.0f, /*enableRetargeting=*/false);
|
||||
m_motion->CalcNodeTransform(m_motionInstance, &transform, GetActor(), skeleton->GetNode(jointIndex), /*timeValue=*/0.0f, /*enableRetargeting=*/false);
|
||||
|
||||
const Transform& bindTransform = bindPose->GetLocalSpaceTransform(jointIndex);
|
||||
EXPECT_THAT(transform, IsClose(bindTransform));
|
||||
@@ -114,7 +114,7 @@ namespace EMotionFX
|
||||
|
||||
// Sample the motion for the foot node.
|
||||
Transform footTransform = Transform::CreateZero(); // Set all to Zero, not identity as this methods might return identity and we want to verify that.
|
||||
m_motion->CalcNodeTransform(m_motionInstance, &footTransform, m_actor.get(), skeleton->GetNode(m_footIndex), /*timeValue=*/0.0f, /*enableRetargeting=*/false);
|
||||
m_motion->CalcNodeTransform(m_motionInstance, &footTransform, GetActor(), skeleton->GetNode(m_footIndex), /*timeValue=*/0.0f, /*enableRetargeting=*/false);
|
||||
|
||||
// Make sure we get an identity transform back as we try to sample a node that doesn't have a submotion in an additive motion.
|
||||
EXPECT_THAT(footTransform, IsClose(Transform::CreateIdentity()));
|
||||
@@ -125,7 +125,7 @@ namespace EMotionFX
|
||||
// Make sure we do not get an identity transform back now that it is a non-additive motion.
|
||||
footTransform.Zero(); // Set all to Zero, not identity as this methods might return identity and we want to verify that.
|
||||
const Transform& expectedFootTransform = m_actorInstance->GetTransformData()->GetCurrentPose()->GetLocalSpaceTransform(m_footIndex);
|
||||
m_motion->CalcNodeTransform(m_motionInstance, &footTransform, m_actor.get(), skeleton->GetNode(m_footIndex), /*timeValue=*/0.0f, /*enableRetargeting=*/false);
|
||||
m_motion->CalcNodeTransform(m_motionInstance, &footTransform, GetActor(), skeleton->GetNode(m_footIndex), /*timeValue=*/0.0f, /*enableRetargeting=*/false);
|
||||
EXPECT_THAT(footTransform, IsClose(expectedFootTransform));
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace EMotionFX
|
||||
// Sample a pose from the motion.
|
||||
Pose pose;
|
||||
pose.LinkToActorInstance(m_actorInstance);
|
||||
pose.InitFromBindPose(m_actor.get());
|
||||
pose.InitFromBindPose(GetActor());
|
||||
pose.Zero();
|
||||
m_motion->Update(&pose, &pose, m_motionInstance);
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <EMotionFX/Source/BlendTreeBlend2Node.h>
|
||||
#include <EMotionFX/Source/BlendTreeBlendNNode.h>
|
||||
#include <EMotionFX/Source/BlendTreeParameterNode.h>
|
||||
#include <EMotionFX/Source/EMotionFXManager.h>
|
||||
#include <EMotionFX/Source/Parameter/FloatSliderParameter.h>
|
||||
#include <EMotionFX/Source/Parameter/ParameterFactory.h>
|
||||
#include <MCore/Source/AttributeFloat.h>
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace EMotionFX
|
||||
|
||||
TEST_P(RagdollRootNodeFixture, RagdollRootNodeIsSimulatedTests)
|
||||
{
|
||||
Physics::RagdollConfiguration& ragdollConfig = m_actor->GetPhysicsSetup()->GetRagdollConfig();
|
||||
Physics::RagdollConfiguration& ragdollConfig = GetActor()->GetPhysicsSetup()->GetRagdollConfig();
|
||||
AZStd::vector<Physics::RagdollNodeConfiguration>& ragdollNodes = ragdollConfig.m_nodes;
|
||||
const RagdollRootNodeParam& param = GetParam();
|
||||
const AZStd::string ragdollRootNodeName = param.m_ragdollRootNode.c_str();
|
||||
|
||||
@@ -24,13 +24,13 @@ namespace EMotionFX
|
||||
CommandSystem::CommandManager commandManager;
|
||||
MCore::CommandGroup commandGroup;
|
||||
|
||||
const AZ::u32 actorId = m_actor->GetID();
|
||||
const AZ::u32 actorId = GetActor()->GetID();
|
||||
const AZStd::vector<AZStd::string> jointNames = GetTestJointNames();
|
||||
const size_t jointCount = jointNames.size();
|
||||
|
||||
|
||||
// 1. Add colliders
|
||||
const AZStd::string serializedBeforeAdd = SerializePhysicsSetup(m_actor.get());
|
||||
const AZStd::string serializedBeforeAdd = SerializePhysicsSetup(GetActor());
|
||||
for (const AZStd::string& jointName : jointNames)
|
||||
{
|
||||
CommandColliderHelpers::AddCollider(actorId, jointName, PhysicsSetup::HitDetection, azrtti_typeid<Physics::BoxShapeConfiguration>(), &commandGroup);
|
||||
@@ -39,23 +39,27 @@ namespace EMotionFX
|
||||
}
|
||||
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
|
||||
const AZStd::string serializedAfterAdd = SerializePhysicsSetup(m_actor.get());
|
||||
EXPECT_EQ(jointCount * 3, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(jointCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box));
|
||||
const AZStd::string serializedAfterAdd = SerializePhysicsSetup(GetActor());
|
||||
EXPECT_EQ(jointCount * 3, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(
|
||||
jointCount,
|
||||
PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/ false, Physics::ShapeType::Box));
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result));
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(serializedBeforeAdd, SerializePhysicsSetup(m_actor.get()));
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(serializedBeforeAdd, SerializePhysicsSetup(GetActor()));
|
||||
|
||||
EXPECT_TRUE(commandManager.Redo(result));
|
||||
EXPECT_EQ(jointCount * 3, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(jointCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box));
|
||||
EXPECT_EQ(serializedAfterAdd, SerializePhysicsSetup(m_actor.get()));
|
||||
EXPECT_EQ(jointCount * 3, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(
|
||||
jointCount,
|
||||
PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/ false, Physics::ShapeType::Box));
|
||||
EXPECT_EQ(serializedAfterAdd, SerializePhysicsSetup(GetActor()));
|
||||
|
||||
|
||||
// 2. Remove colliders
|
||||
commandGroup.RemoveAllCommands();
|
||||
const AZStd::string serializedBeforeRemove = SerializePhysicsSetup(m_actor.get());
|
||||
const AZStd::string serializedBeforeRemove = SerializePhysicsSetup(GetActor());
|
||||
|
||||
size_t colliderIndexToRemove = 1;
|
||||
for (const AZStd::string& jointName : jointNames)
|
||||
@@ -64,18 +68,24 @@ namespace EMotionFX
|
||||
}
|
||||
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
|
||||
const AZStd::string serializedAfterRemove = SerializePhysicsSetup(m_actor.get());
|
||||
EXPECT_EQ(jointCount * 2, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Capsule));
|
||||
const AZStd::string serializedAfterRemove = SerializePhysicsSetup(GetActor());
|
||||
EXPECT_EQ(jointCount * 2, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(
|
||||
0,
|
||||
PhysicsSetupUtils::CountColliders(
|
||||
GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/ false, Physics::ShapeType::Capsule));
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result));
|
||||
EXPECT_EQ(jointCount * 3, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(serializedBeforeRemove, SerializePhysicsSetup(m_actor.get()));
|
||||
EXPECT_EQ(jointCount * 3, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(serializedBeforeRemove, SerializePhysicsSetup(GetActor()));
|
||||
|
||||
EXPECT_TRUE(commandManager.Redo(result));
|
||||
EXPECT_EQ(jointCount * 2, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Capsule));
|
||||
EXPECT_EQ(serializedAfterRemove, SerializePhysicsSetup(m_actor.get()));
|
||||
EXPECT_EQ(jointCount * 2, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(
|
||||
0,
|
||||
PhysicsSetupUtils::CountColliders(
|
||||
GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/ false, Physics::ShapeType::Capsule));
|
||||
EXPECT_EQ(serializedAfterRemove, SerializePhysicsSetup(GetActor()));
|
||||
}
|
||||
|
||||
TEST_F(ColliderCommandTests, AddRemove1000Colliders)
|
||||
@@ -84,11 +94,11 @@ namespace EMotionFX
|
||||
CommandSystem::CommandManager commandManager;
|
||||
MCore::CommandGroup commandGroup;
|
||||
|
||||
const AZ::u32 actorId = m_actor->GetID();
|
||||
const AZ::u32 actorId = GetActor()->GetID();
|
||||
const AZStd::string jointName = "Bip01__pelvis";
|
||||
|
||||
// 1. Add colliders
|
||||
const AZStd::string serializedBeforeAdd = SerializePhysicsSetup(m_actor.get());
|
||||
const AZStd::string serializedBeforeAdd = SerializePhysicsSetup(GetActor());
|
||||
const size_t colliderCount = 1000;
|
||||
for (AZ::u32 i = 0; i < colliderCount; ++i)
|
||||
{
|
||||
@@ -96,51 +106,51 @@ namespace EMotionFX
|
||||
}
|
||||
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
|
||||
const AZStd::string serializedAfterAdd = SerializePhysicsSetup(m_actor.get());
|
||||
EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box));
|
||||
const AZStd::string serializedAfterAdd = SerializePhysicsSetup(GetActor());
|
||||
EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box));
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result));
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(serializedBeforeAdd, SerializePhysicsSetup(m_actor.get()));
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(serializedBeforeAdd, SerializePhysicsSetup(GetActor()));
|
||||
|
||||
EXPECT_TRUE(commandManager.Redo(result));
|
||||
EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box));
|
||||
EXPECT_EQ(serializedAfterAdd, SerializePhysicsSetup(m_actor.get()));
|
||||
EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box));
|
||||
EXPECT_EQ(serializedAfterAdd, SerializePhysicsSetup(GetActor()));
|
||||
|
||||
// 2. Clear colliders
|
||||
commandGroup.RemoveAllCommands();
|
||||
const AZStd::string serializedBeforeRemove = SerializePhysicsSetup(m_actor.get());
|
||||
const AZStd::string serializedBeforeRemove = SerializePhysicsSetup(GetActor());
|
||||
CommandColliderHelpers::ClearColliders(actorId, jointName, PhysicsSetup::HitDetection, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
|
||||
|
||||
const AZStd::string serializedAfterRemove = SerializePhysicsSetup(m_actor.get());
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box));
|
||||
const AZStd::string serializedAfterRemove = SerializePhysicsSetup(GetActor());
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box));
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result));
|
||||
EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(serializedBeforeRemove, SerializePhysicsSetup(m_actor.get()));
|
||||
EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(serializedBeforeRemove, SerializePhysicsSetup(GetActor()));
|
||||
|
||||
EXPECT_TRUE(commandManager.Redo(result));
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box));
|
||||
EXPECT_EQ(serializedAfterRemove, SerializePhysicsSetup(m_actor.get()));
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection));
|
||||
EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box));
|
||||
EXPECT_EQ(serializedAfterRemove, SerializePhysicsSetup(GetActor()));
|
||||
}
|
||||
|
||||
TEST_F(ColliderCommandTests, AutoSizingColliders)
|
||||
{
|
||||
CommandSystem::CommandManager commandManager;
|
||||
|
||||
const AZ::u32 actorId = m_actor->GetID();
|
||||
const AZ::u32 actorId = GetActor()->GetID();
|
||||
const AZStd::vector<AZStd::string> jointNames = GetTestJointNames();
|
||||
ASSERT_TRUE(jointNames.size() > 0) << "The joint names test data needs at least one joint for this test.";
|
||||
const AZStd::string& jointName = jointNames[0];
|
||||
|
||||
CommandColliderHelpers::AddCollider(actorId, jointName, PhysicsSetup::HitDetection, azrtti_typeid<Physics::BoxShapeConfiguration>());
|
||||
|
||||
const AZStd::shared_ptr<PhysicsSetup>& physicsSetup = m_actor->GetPhysicsSetup();
|
||||
const AZStd::shared_ptr<PhysicsSetup>& physicsSetup = GetActor()->GetPhysicsSetup();
|
||||
Physics::CharacterColliderConfiguration* colliderConfig = physicsSetup->GetColliderConfigByType(PhysicsSetup::HitDetection);
|
||||
EXPECT_NE(colliderConfig, nullptr) << "Collider config should be valid after we added a collider to it.";
|
||||
|
||||
@@ -184,11 +194,11 @@ namespace EMotionFX
|
||||
const PhysicsSetup::ColliderConfigType m_configType = PhysicsSetup::ColliderConfigType::HitDetection;
|
||||
|
||||
// Add collider to the given joint first.
|
||||
const AZStd::shared_ptr<PhysicsSetup>& physicsSetup = m_actor->GetPhysicsSetup();
|
||||
EXPECT_TRUE(CommandColliderHelpers::AddCollider(m_actor->GetID(), m_jointName, m_configType, param.m_shapeType));
|
||||
const AZStd::shared_ptr<PhysicsSetup>& physicsSetup = GetActor()->GetPhysicsSetup();
|
||||
EXPECT_TRUE(CommandColliderHelpers::AddCollider(GetActor()->GetID(), m_jointName, m_configType, param.m_shapeType));
|
||||
Physics::CharacterColliderConfiguration* characterColliderConfig = physicsSetup->GetColliderConfigByType(m_configType);
|
||||
ASSERT_TRUE(characterColliderConfig != nullptr);
|
||||
Physics::CharacterColliderNodeConfiguration* nodeConfig = CommandColliderHelpers::GetCreateNodeConfig(m_actor.get(), m_jointName, *characterColliderConfig, result);
|
||||
Physics::CharacterColliderNodeConfiguration* nodeConfig = CommandColliderHelpers::GetCreateNodeConfig(GetActor(), m_jointName, *characterColliderConfig, result);
|
||||
ASSERT_TRUE(nodeConfig != nullptr);
|
||||
EXPECT_EQ(nodeConfig->m_shapes.size(), 1);
|
||||
|
||||
@@ -200,7 +210,8 @@ namespace EMotionFX
|
||||
|
||||
// Create the adjust collider command and using the data from the test parameter.
|
||||
MCore::Command* orgCommand = CommandSystem::GetCommandManager()->FindCommand(CommandAdjustCollider::s_commandName);
|
||||
CommandAdjustCollider* command = aznew CommandAdjustCollider(m_actor->GetID(), m_jointName, m_configType, /*colliderIndex=*/0, orgCommand);
|
||||
CommandAdjustCollider* command =
|
||||
aznew CommandAdjustCollider(GetActor()->GetID(), m_jointName, m_configType, /*colliderIndex=*/0, orgCommand);
|
||||
command->SetOldIsTrigger(colliderConfig->m_isTrigger);
|
||||
command->SetIsTrigger(param.m_isTrigger);
|
||||
command->SetOldPosition(colliderConfig->m_position);
|
||||
@@ -223,9 +234,9 @@ namespace EMotionFX
|
||||
}
|
||||
|
||||
// Check execute.
|
||||
const AZStd::string serializedBeforeExecute = SerializePhysicsSetup(m_actor.get());
|
||||
const AZStd::string serializedBeforeExecute = SerializePhysicsSetup(GetActor());
|
||||
EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommand(command, result));
|
||||
const AZStd::string serializedAfterExecute = SerializePhysicsSetup(m_actor.get());
|
||||
const AZStd::string serializedAfterExecute = SerializePhysicsSetup(GetActor());
|
||||
|
||||
EXPECT_EQ(colliderConfig->m_isTrigger, param.m_isTrigger);
|
||||
EXPECT_EQ(colliderConfig->m_position, param.m_position);
|
||||
@@ -243,12 +254,12 @@ namespace EMotionFX
|
||||
|
||||
// Check undo.
|
||||
EXPECT_TRUE(CommandSystem::GetCommandManager()->Undo(result));
|
||||
const AZStd::string serializedAfterUndo = SerializePhysicsSetup(m_actor.get());
|
||||
const AZStd::string serializedAfterUndo = SerializePhysicsSetup(GetActor());
|
||||
EXPECT_EQ(serializedAfterUndo, serializedBeforeExecute);
|
||||
|
||||
// Check redo.
|
||||
EXPECT_TRUE(CommandSystem::GetCommandManager()->Redo(result));
|
||||
const AZStd::string serializedAfterRedo = SerializePhysicsSetup(m_actor.get());
|
||||
const AZStd::string serializedAfterRedo = SerializePhysicsSetup(GetActor());
|
||||
EXPECT_EQ(serializedAfterRedo, serializedAfterExecute);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,9 +13,11 @@
|
||||
#include <QtTest>
|
||||
|
||||
#include <Tests/UI/UIFixture.h>
|
||||
#include <Tests/TestAssetCode/JackActor.h>
|
||||
#include <Tests/TestAssetCode/TestActorAssets.h>
|
||||
#include <EMotionFX/CommandSystem/Source/CommandManager.h>
|
||||
#include <EMotionFX/Source/Actor.h>
|
||||
#include <EMotionFX/Source/AutoRegisteredActor.h>
|
||||
#include <EMotionFX/Source/ActorManager.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
@@ -33,14 +35,12 @@ namespace EMotionFX
|
||||
ASSERT_EQ(GetActorManager().GetNumActors(), 0);
|
||||
|
||||
// Load an Actor
|
||||
const char* actorCmd{ "ImportActor -filename @engroot@/Gems/EMotionFX/Code/Tests/TestAssets/Rin/rin.actor" };
|
||||
{
|
||||
AZStd::string result;
|
||||
EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommand(actorCmd, result)) << result.c_str();
|
||||
}
|
||||
AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}");
|
||||
AZ::Data::Asset<Integration::ActorAsset> actorAsset =
|
||||
TestActorAssets::CreateActorAssetAndRegister<JackNoMeshesActor>(actorAssetId, "Jack");
|
||||
|
||||
// Ensure the Actor is correct
|
||||
ASSERT_TRUE(GetActorManager().FindActorByName("rinActor"));
|
||||
ASSERT_TRUE(GetActorManager().FindActorByName("Jack"));
|
||||
EXPECT_EQ(GetActorManager().GetNumActors(), 1);
|
||||
}
|
||||
} // namespace EMotionFX
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <EMotionFX/Source/ActorManager.h>
|
||||
#include <EMotionFX/Source/AnimGraphMotionNode.h>
|
||||
#include <EMotionFX/Source/MotionSet.h>
|
||||
#include <EMotionFX/Source/Motion.h>
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <EMotionFX/Source/Actor.h>
|
||||
#include <EMotionFX/Source/ActorInstance.h>
|
||||
#include <EMotionFX/Source/ActorUpdateScheduler.h>
|
||||
#include <EMotionFX/Source/EMotionFXManager.h>
|
||||
#include <EMotionFX/Source/ActorManager.h>
|
||||
#include <EMotionFX/Source/MultiThreadScheduler.h>
|
||||
#include <Tests/SystemComponentFixture.h>
|
||||
#include <Tests/TestAssetCode/JackActor.h>
|
||||
|
||||
@@ -19,11 +19,13 @@
|
||||
#include <EMotionFX/Source/AnimGraphEntryNode.h>
|
||||
#include <EMotionFX/Source/AnimGraphHubNode.h>
|
||||
#include <EMotionFX/Source/AnimGraphManager.h>
|
||||
#include <EMotionFX/Source/ActorManager.h>
|
||||
#include <EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
|
||||
#include <EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h>
|
||||
#include <EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.h>
|
||||
#include <Tests/TestAssetCode/ActorFactory.h>
|
||||
#include <Tests/TestAssetCode/SimpleActors.h>
|
||||
#include <Tests/TestAssetCode/TestActorAssets.h>
|
||||
#include <EMotionFX/Source/MotionManager.h>
|
||||
|
||||
namespace EMotionFX
|
||||
@@ -78,7 +80,8 @@ namespace EMotionFX
|
||||
EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommandGroup(group, commandResult)) << commandResult.c_str();
|
||||
|
||||
// Create temp Actor
|
||||
m_actor = ActorFactory::CreateAndInit<SimpleJointChainActor>(1, "tempActor");
|
||||
AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}");
|
||||
m_actorAsset = TestActorAssets::CreateActorAssetAndRegister<SimpleJointChainActor>(actorAssetId, 1, "tempActor");
|
||||
|
||||
// Cache some local poitners.
|
||||
m_animGraphPlugin = static_cast<EMStudio::AnimGraphPlugin*>(EMStudio::GetPluginManager()->FindActivePlugin(EMStudio::AnimGraphPlugin::CLASS_ID));
|
||||
@@ -90,6 +93,7 @@ namespace EMotionFX
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
GetEMotionFX().GetActorManager()->UnregisterAllActors();
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
delete m_animGraph;
|
||||
UIFixture::TearDown();
|
||||
@@ -104,7 +108,7 @@ namespace EMotionFX
|
||||
AZStd::string m_entryNodeName = "testEntry";
|
||||
AnimGraph* m_animGraph = nullptr;
|
||||
EMStudio::AnimGraphPlugin* m_animGraphPlugin = nullptr;
|
||||
AutoRegisteredActor m_actor;
|
||||
AZ::Data::Asset<Integration::ActorAsset> m_actorAsset;
|
||||
};
|
||||
|
||||
TEST_F(PopulatedAnimGraphFixture, CanActivateValidGraph)
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <EMotionFX/Source/AnimGraphMotionNode.h>
|
||||
#include <EMotionFX/Source/AnimGraphReferenceNode.h>
|
||||
#include <EMotionFX/Source/AnimGraphStateMachine.h>
|
||||
#include <EMotionFX/Source/AutoRegisteredActor.h>
|
||||
#include <EMotionFX/Source/EMotionFXManager.h>
|
||||
#include <EMotionFX/Source/Parameter/BoolParameter.h>
|
||||
#include <EMotionFX/Source/Parameter/FloatSliderParameter.h>
|
||||
@@ -43,6 +42,7 @@
|
||||
#include <Tests/TestAssetCode/SimpleActors.h>
|
||||
#include <Tests/ProvidesUI/AnimGraph/SimpleAnimGraphUIFixture.h>
|
||||
#include <Tests/TestAssetCode/ActorFactory.h>
|
||||
#include <Tests/TestAssetCode/TestActorAssets.h>
|
||||
#include <Tests/Mocks/EventHandler.h>
|
||||
|
||||
namespace EMotionFX
|
||||
@@ -423,7 +423,10 @@ namespace EMotionFX
|
||||
using testing::Eq;
|
||||
using testing::Not;
|
||||
|
||||
AutoRegisteredActor actor = EMotionFX::ActorFactory::CreateAndInit<EMotionFX::SimpleJointChainActor>(1);
|
||||
AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}");
|
||||
AZ::Data::Asset<Integration::ActorAsset> actorAsset =
|
||||
TestActorAssets::CreateActorAssetAndRegister<SimpleJointChainActor>(actorAssetId, 1);
|
||||
|
||||
auto motionSet = AZStd::make_unique<EMotionFX::MotionSet>();
|
||||
|
||||
{
|
||||
@@ -432,7 +435,7 @@ namespace EMotionFX
|
||||
}
|
||||
|
||||
auto* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(0);
|
||||
auto* actorInstance = EMotionFX::ActorInstance::Create(actor.get());
|
||||
auto* actorInstance = EMotionFX::ActorInstance::Create(actorAsset->GetActor());
|
||||
auto* animGraphInstance = EMotionFX::AnimGraphInstance::Create(animGraph, actorInstance, motionSet.get());
|
||||
actorInstance->SetAnimGraphInstance(animGraphInstance);
|
||||
|
||||
|
||||
@@ -24,12 +24,11 @@
|
||||
#include <EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.h>
|
||||
|
||||
#include <EMotionFX/Source/Actor.h>
|
||||
#include <EMotionFX/Source/AutoRegisteredActor.h>
|
||||
#include <Tests/TestAssetCode/SimpleActors.h>
|
||||
#include <Tests/TestAssetCode/ActorFactory.h>
|
||||
#include <Tests/TestAssetCode/TestActorAssets.h>
|
||||
#include <Tests/UI/ModalPopupHandler.h>
|
||||
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
|
||||
@@ -58,8 +57,10 @@ namespace EMotionFX
|
||||
ASSERT_EQ(GetMotionManager().GetNumMotions(), 0) << "Expected exactly zero motions";
|
||||
|
||||
// Create Actor, AnimGraph, Motionset and Motion
|
||||
AutoRegisteredActor actor = ActorFactory::CreateAndInit<SimpleJointChainActor>(2, "SampleActor");
|
||||
ActorInstance::Create(actor.get());
|
||||
AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}");
|
||||
AZ::Data::Asset<Integration::ActorAsset> actorAsset =
|
||||
TestActorAssets::CreateActorAssetAndRegister<SimpleJointChainActor>(actorAssetId, 2, "SampleActor");
|
||||
ActorInstance::Create(actorAsset->GetActor());
|
||||
{
|
||||
AZStd::string result;
|
||||
ASSERT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommand(createAnimGraphCmd, result)) << result.c_str();
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <Tests/Mocks/PhysicsSystem.h>
|
||||
#include <Tests/TestAssetCode/ActorFactory.h>
|
||||
#include <Tests/TestAssetCode/SimpleActors.h>
|
||||
#include <Tests/TestAssetCode/TestActorAssets.h>
|
||||
#include <Tests/UI/UIFixture.h>
|
||||
|
||||
namespace EMotionFX
|
||||
@@ -79,7 +80,11 @@ namespace EMotionFX
|
||||
TEST_F(CopyPasteRagdollCollidersFixture, CanCopyCollider)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_EDITOR_TESTS
|
||||
{
|
||||
AutoRegisteredActor actor{ActorFactory::CreateAndInit<SimpleJointChainActor>(4)};
|
||||
AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}");
|
||||
AZ::Data::Asset<Integration::ActorAsset> actorAsset =
|
||||
TestActorAssets::CreateActorAssetAndRegister<SimpleJointChainActor>(actorAssetId, 4);
|
||||
const Actor* actor = actorAsset->GetActor();
|
||||
|
||||
const Physics::RagdollConfiguration& ragdollConfig = actor->GetPhysicsSetup()->GetRagdollConfig();
|
||||
const Physics::CharacterColliderConfiguration& simulatedObjectConfig = actor->GetPhysicsSetup()->GetSimulatedObjectColliderConfig();
|
||||
|
||||
@@ -104,8 +109,7 @@ namespace EMotionFX
|
||||
|
||||
{
|
||||
AZStd::string result;
|
||||
EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommand(
|
||||
"Select -actorId " + AZStd::to_string(actor->GetID()),
|
||||
EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommand("Select -actorId " + AZStd::to_string(actor->GetID()),
|
||||
result))
|
||||
<< result.c_str();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <EMotionFX/CommandSystem/Source/CommandManager.h>
|
||||
#include <EMotionFX/CommandSystem/Source/RagdollCommands.h>
|
||||
#include <EMotionFX/Source/AutoRegisteredActor.h>
|
||||
#include <EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
|
||||
#include <Editor/Plugins/Ragdoll/RagdollJointLimitWidget.h>
|
||||
#include <Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.h>
|
||||
@@ -25,6 +24,7 @@
|
||||
#include <Tests/Mocks/PhysicsSystem.h>
|
||||
#include <Tests/TestAssetCode/ActorFactory.h>
|
||||
#include <Tests/TestAssetCode/SimpleActors.h>
|
||||
#include <Tests/TestAssetCode/TestActorAssets.h>
|
||||
#include <Tests/UI/UIFixture.h>
|
||||
|
||||
namespace EMotionFX
|
||||
@@ -76,7 +76,9 @@ namespace EMotionFX
|
||||
return AZStd::make_unique<D6JointLimitConfiguration>();
|
||||
});
|
||||
|
||||
AutoRegisteredActor actor {ActorFactory::CreateAndInit<SimpleJointChainActor>(4)};
|
||||
AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}");
|
||||
AZ::Data::Asset<Integration::ActorAsset> actorAsset = TestActorAssets::CreateActorAssetAndRegister<SimpleJointChainActor>(actorAssetId, 4);
|
||||
const Actor* actor = actorAsset->GetActor();
|
||||
|
||||
{
|
||||
AZStd::string result;
|
||||
|
||||
@@ -99,28 +99,28 @@ namespace EMotionFX
|
||||
"l_hand",
|
||||
};
|
||||
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_shldr"}, &commandGroup);
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_shldr"}, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str();
|
||||
|
||||
EXPECT_THAT(
|
||||
GetRagdollJointNames(m_actor.get()),
|
||||
GetRagdollJointNames(GetActor()),
|
||||
testing::UnorderedPointwise(
|
||||
StrEq(),
|
||||
jointsToLeftShoulder
|
||||
)
|
||||
);
|
||||
|
||||
const AZStd::string serializedBeforeHandAdded = SerializePhysicsSetup(m_actor.get());
|
||||
const AZStd::string serializedBeforeHandAdded = SerializePhysicsSetup(GetActor());
|
||||
|
||||
// Adding l_hand should add l_upArm and l_loArm as well
|
||||
commandGroup.RemoveAllCommands();
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_hand"}, &commandGroup);
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_hand"}, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str();
|
||||
|
||||
const AZStd::string serializedAfterHandAdded = SerializePhysicsSetup(m_actor.get());
|
||||
const AZStd::string serializedAfterHandAdded = SerializePhysicsSetup(GetActor());
|
||||
|
||||
EXPECT_THAT(
|
||||
GetRagdollJointNames(m_actor.get()),
|
||||
GetRagdollJointNames(GetActor()),
|
||||
testing::UnorderedPointwise(
|
||||
StrEq(),
|
||||
jointsToLeftHand
|
||||
@@ -129,23 +129,23 @@ namespace EMotionFX
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result)) << result.c_str();
|
||||
EXPECT_THAT(
|
||||
GetRagdollJointNames(m_actor.get()),
|
||||
GetRagdollJointNames(GetActor()),
|
||||
testing::UnorderedPointwise(
|
||||
StrEq(),
|
||||
jointsToLeftShoulder
|
||||
)
|
||||
);
|
||||
EXPECT_THAT(SerializePhysicsSetup(m_actor.get()), StrEq(serializedBeforeHandAdded));
|
||||
EXPECT_THAT(SerializePhysicsSetup(GetActor()), StrEq(serializedBeforeHandAdded));
|
||||
|
||||
EXPECT_TRUE(commandManager.Redo(result)) << result.c_str();
|
||||
EXPECT_THAT(
|
||||
GetRagdollJointNames(m_actor.get()),
|
||||
GetRagdollJointNames(GetActor()),
|
||||
testing::UnorderedPointwise(
|
||||
StrEq(),
|
||||
jointsToLeftHand
|
||||
)
|
||||
);
|
||||
EXPECT_THAT(SerializePhysicsSetup(m_actor.get()), StrEq(serializedAfterHandAdded));
|
||||
EXPECT_THAT(SerializePhysicsSetup(GetActor()), StrEq(serializedAfterHandAdded));
|
||||
}
|
||||
|
||||
TEST_F(RagdollCommandTests, AddJointHigherInHierarchy)
|
||||
@@ -166,10 +166,10 @@ namespace EMotionFX
|
||||
"l_hand",
|
||||
};
|
||||
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_hand"}, &commandGroup);
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_hand"}, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str();
|
||||
EXPECT_THAT(
|
||||
GetRagdollJointNames(m_actor.get()),
|
||||
GetRagdollJointNames(GetActor()),
|
||||
testing::UnorderedPointwise(
|
||||
StrEq(),
|
||||
jointsToLeftHand
|
||||
@@ -178,10 +178,10 @@ namespace EMotionFX
|
||||
|
||||
// l_shldr should already be in the ragdoll, so adding it should do nothing
|
||||
commandGroup.RemoveAllCommands();
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_shldr"}, &commandGroup);
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_shldr"}, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str();
|
||||
EXPECT_THAT(
|
||||
GetRagdollJointNames(m_actor.get()),
|
||||
GetRagdollJointNames(GetActor()),
|
||||
testing::UnorderedPointwise(
|
||||
StrEq(),
|
||||
jointsToLeftHand
|
||||
@@ -190,11 +190,11 @@ namespace EMotionFX
|
||||
|
||||
// Undo here undoes the addition of l_hand
|
||||
EXPECT_TRUE(commandManager.Undo(result)) << result.c_str();
|
||||
EXPECT_TRUE(GetRagdollJointNames(m_actor.get()).empty());
|
||||
EXPECT_TRUE(GetRagdollJointNames(GetActor()).empty());
|
||||
|
||||
EXPECT_TRUE(commandManager.Redo(result)) << result.c_str();
|
||||
EXPECT_THAT(
|
||||
GetRagdollJointNames(m_actor.get()),
|
||||
GetRagdollJointNames(GetActor()),
|
||||
testing::UnorderedPointwise(
|
||||
StrEq(),
|
||||
jointsToLeftHand
|
||||
@@ -221,16 +221,16 @@ namespace EMotionFX
|
||||
};
|
||||
|
||||
// Add a joint to the ragdoll that does not make a chain all the way to the root
|
||||
EXPECT_TRUE(commandManager.ExecuteCommand(aznew CommandAddRagdollJoint(m_actor->GetID(), "l_shldr"), result)) << result.c_str();
|
||||
EXPECT_TRUE(commandManager.ExecuteCommand(aznew CommandAddRagdollJoint(GetActor()->GetID(), "l_shldr"), result)) << result.c_str();
|
||||
EXPECT_THAT(
|
||||
GetRagdollJointNames(m_actor.get()),
|
||||
GetRagdollJointNames(GetActor()),
|
||||
testing::UnorderedPointwise(StrEq(), AZStd::vector<AZStd::string>{"l_shldr"})
|
||||
);
|
||||
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_hand"}, &commandGroup);
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_hand"}, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str();
|
||||
EXPECT_THAT(
|
||||
GetRagdollJointNames(m_actor.get()),
|
||||
GetRagdollJointNames(GetActor()),
|
||||
testing::UnorderedPointwise(StrEq(), jointsToLeftHand)
|
||||
);
|
||||
}
|
||||
@@ -250,17 +250,17 @@ namespace EMotionFX
|
||||
};
|
||||
|
||||
// Add joints from the root to the left hand
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_hand"}, &commandGroup);
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_hand"}, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str();
|
||||
|
||||
// Removing the left shoulder should remove the elbow, wrist, and hand
|
||||
// as well
|
||||
commandGroup.RemoveAllCommands();
|
||||
CommandRagdollHelpers::RemoveJointsFromRagdoll(m_actor->GetID(), {"l_shldr"}, &commandGroup);
|
||||
CommandRagdollHelpers::RemoveJointsFromRagdoll(GetActor()->GetID(), {"l_shldr"}, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str();
|
||||
|
||||
EXPECT_THAT(
|
||||
GetRagdollJointNames(m_actor.get()),
|
||||
GetRagdollJointNames(GetActor()),
|
||||
testing::UnorderedPointwise(StrEq(), jointsToSpine3)
|
||||
);
|
||||
}
|
||||
@@ -271,24 +271,24 @@ namespace EMotionFX
|
||||
CommandSystem::CommandManager commandManager;
|
||||
MCore::CommandGroup commandGroup;
|
||||
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_hand"}, &commandGroup);
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_hand"}, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str();
|
||||
|
||||
const AZStd::string serializedBeforeSphereAdded = SerializePhysicsSetup(m_actor.get());
|
||||
const AZStd::string serializedBeforeSphereAdded = SerializePhysicsSetup(GetActor());
|
||||
|
||||
CommandColliderHelpers::AddCollider(m_actor->GetID(), "l_hand",
|
||||
CommandColliderHelpers::AddCollider(GetActor()->GetID(), "l_hand",
|
||||
PhysicsSetup::Ragdoll, azrtti_typeid<Physics::SphereShapeConfiguration>());
|
||||
|
||||
const AZStd::string serializedAfterSphereAdded = SerializePhysicsSetup(m_actor.get());
|
||||
const AZStd::string serializedAfterSphereAdded = SerializePhysicsSetup(GetActor());
|
||||
|
||||
EXPECT_THAT(serializedAfterSphereAdded, ::testing::Not(StrEq(serializedBeforeSphereAdded)));
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result)) << result.c_str();
|
||||
|
||||
EXPECT_THAT(SerializePhysicsSetup(m_actor.get()), StrEq(serializedBeforeSphereAdded));
|
||||
EXPECT_THAT(SerializePhysicsSetup(GetActor()), StrEq(serializedBeforeSphereAdded));
|
||||
|
||||
EXPECT_TRUE(commandManager.Redo(result)) << result.c_str();
|
||||
|
||||
EXPECT_THAT(SerializePhysicsSetup(m_actor.get()), StrEq(serializedAfterSphereAdded));
|
||||
EXPECT_THAT(SerializePhysicsSetup(GetActor()), StrEq(serializedAfterSphereAdded));
|
||||
}
|
||||
} // namespace EMotionFX
|
||||
|
||||
@@ -55,25 +55,25 @@ namespace EMotionFX
|
||||
CommandSystem::CommandManager commandManager;
|
||||
MCore::CommandGroup commandGroup;
|
||||
|
||||
const uint32 actorId = m_actor->GetID();
|
||||
const uint32 actorId = GetActor()->GetID();
|
||||
const AZStd::vector<AZStd::string> jointNames = GetTestJointNames();
|
||||
|
||||
// 1. Add simulated object.
|
||||
const AZStd::string serializedBeforeAdd = SerializeSimulatedObjectSetup(m_actor.get());
|
||||
const AZStd::string serializedBeforeAdd = SerializeSimulatedObjectSetup(GetActor());
|
||||
CommandSimulatedObjectHelpers::AddSimulatedObject(actorId, AZStd::nullopt, &commandGroup);
|
||||
CommandSimulatedObjectHelpers::AddSimulatedObject(actorId, AZStd::nullopt, &commandGroup);
|
||||
CommandSimulatedObjectHelpers::AddSimulatedObject(actorId, AZStd::nullopt, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
|
||||
const AZStd::string serializedAfterAdd = SerializeSimulatedObjectSetup(m_actor.get());
|
||||
EXPECT_EQ(3, CountSimulatedObjects(m_actor.get()));
|
||||
const AZStd::string serializedAfterAdd = SerializeSimulatedObjectSetup(GetActor());
|
||||
EXPECT_EQ(3, CountSimulatedObjects(GetActor()));
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result));
|
||||
EXPECT_EQ(0, CountSimulatedObjects(m_actor.get()));
|
||||
EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(0, CountSimulatedObjects(GetActor()));
|
||||
EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(GetActor()));
|
||||
|
||||
EXPECT_TRUE(commandManager.Redo(result));
|
||||
EXPECT_EQ(3, CountSimulatedObjects(m_actor.get()));
|
||||
EXPECT_EQ(serializedAfterAdd, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(3, CountSimulatedObjects(GetActor()));
|
||||
EXPECT_EQ(serializedAfterAdd, SerializeSimulatedObjectSetup(GetActor()));
|
||||
|
||||
// 2. Remove simulated object.
|
||||
commandGroup.RemoveAllCommands();
|
||||
@@ -81,22 +81,22 @@ namespace EMotionFX
|
||||
CommandSimulatedObjectHelpers::RemoveSimulatedObject(actorId, 0, &commandGroup);
|
||||
CommandSimulatedObjectHelpers::RemoveSimulatedObject(actorId, 0, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
|
||||
EXPECT_EQ(0, CountSimulatedObjects(m_actor.get()));
|
||||
EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(0, CountSimulatedObjects(GetActor()));
|
||||
EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(GetActor()));
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result));
|
||||
EXPECT_EQ(3, CountSimulatedObjects(m_actor.get()));
|
||||
EXPECT_EQ(serializedAfterAdd, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(3, CountSimulatedObjects(GetActor()));
|
||||
EXPECT_EQ(serializedAfterAdd, SerializeSimulatedObjectSetup(GetActor()));
|
||||
|
||||
EXPECT_TRUE(commandManager.Redo(result));
|
||||
EXPECT_EQ(0, CountSimulatedObjects(m_actor.get()));
|
||||
EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(0, CountSimulatedObjects(GetActor()));
|
||||
EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(GetActor()));
|
||||
|
||||
// 3. Add simulated joints.
|
||||
// 3.1 Add a simulated object first to put in the simulated joints.
|
||||
commandGroup.RemoveAllCommands();
|
||||
CommandSimulatedObjectHelpers::AddSimulatedObject(actorId);
|
||||
const AZStd::string serialized3_1 = SerializeSimulatedObjectSetup(m_actor.get());
|
||||
const AZStd::string serialized3_1 = SerializeSimulatedObjectSetup(GetActor());
|
||||
|
||||
// 3.2 Add simulated joints.
|
||||
// Joint hierarchy as follow:
|
||||
@@ -105,7 +105,7 @@ namespace EMotionFX
|
||||
// --l_loLeg
|
||||
// --l_ankle
|
||||
// --l_ball
|
||||
const Skeleton* skeleton = m_actor->GetSkeleton();
|
||||
const Skeleton* skeleton = GetActor()->GetSkeleton();
|
||||
const size_t l_upLegIdx = skeleton->FindNodeByName("l_upLeg")->GetNodeIndex();
|
||||
const size_t l_upLegRollIdx = skeleton->FindNodeByName("l_upLegRoll")->GetNodeIndex();
|
||||
const size_t l_loLegIdx = skeleton->FindNodeByName("l_loLeg")->GetNodeIndex();
|
||||
@@ -113,33 +113,33 @@ namespace EMotionFX
|
||||
const size_t l_ballIdx = skeleton->FindNodeByName("l_ball")->GetNodeIndex();
|
||||
CommandSimulatedObjectHelpers::AddSimulatedJoints(actorId, {l_upLegIdx, l_upLegRollIdx, l_loLegIdx, l_ankleIdx, l_ballIdx}, 0, false, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
|
||||
const AZStd::string serialized3_2 = SerializeSimulatedObjectSetup(m_actor.get());
|
||||
EXPECT_EQ(5, CountSimulatedJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(2, CountChildJoints(m_actor.get(), 0, l_upLegIdx));
|
||||
EXPECT_EQ(0, CountChildJoints(m_actor.get(), 0, l_upLegRollIdx));
|
||||
EXPECT_EQ(1, CountChildJoints(m_actor.get(), 0, l_loLegIdx));
|
||||
const AZStd::string serialized3_2 = SerializeSimulatedObjectSetup(GetActor());
|
||||
EXPECT_EQ(5, CountSimulatedJoints(GetActor(), 0));
|
||||
EXPECT_EQ(2, CountChildJoints(GetActor(), 0, l_upLegIdx));
|
||||
EXPECT_EQ(0, CountChildJoints(GetActor(), 0, l_upLegRollIdx));
|
||||
EXPECT_EQ(1, CountChildJoints(GetActor(), 0, l_loLegIdx));
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result));
|
||||
EXPECT_EQ(0, CountSimulatedJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(0, CountSimulatedJoints(GetActor(), 0));
|
||||
EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(GetActor()));
|
||||
|
||||
EXPECT_TRUE(commandManager.Redo(result));
|
||||
EXPECT_EQ(5, CountSimulatedJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(5, CountSimulatedJoints(GetActor(), 0));
|
||||
EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(GetActor()));
|
||||
|
||||
// 4 Remove simulated joints.
|
||||
// 4.1 Test sparse chain.
|
||||
EXPECT_EQ(1, CountRootJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(1, CountRootJoints(GetActor(), 0));
|
||||
commandGroup.RemoveAllCommands();
|
||||
CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actorId, {l_loLegIdx}, 0, false, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
|
||||
EXPECT_EQ(2, CountRootJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(2, CountRootJoints(GetActor(), 0));
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result));
|
||||
EXPECT_EQ(1, CountRootJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(1, CountRootJoints(GetActor(), 0));
|
||||
|
||||
EXPECT_TRUE(commandManager.Redo(result));
|
||||
EXPECT_EQ(2, CountRootJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(2, CountRootJoints(GetActor(), 0));
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result));
|
||||
|
||||
@@ -147,23 +147,23 @@ namespace EMotionFX
|
||||
commandGroup.RemoveAllCommands();
|
||||
CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actorId, { l_upLegIdx, l_upLegRollIdx, l_loLegIdx, l_ankleIdx, l_ballIdx }, 0, false, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
|
||||
EXPECT_EQ(0, CountSimulatedJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(0, CountSimulatedJoints(GetActor(), 0));
|
||||
EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(GetActor()));
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result));
|
||||
EXPECT_EQ(5, CountSimulatedJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(5, CountSimulatedJoints(GetActor(), 0));
|
||||
EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(GetActor()));
|
||||
|
||||
// 4.3 Test removing the root joint and children.
|
||||
commandGroup.RemoveAllCommands();
|
||||
CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actorId, { l_upLegIdx }, 0, true, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
|
||||
EXPECT_EQ(0, CountSimulatedJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(0, CountSimulatedJoints(GetActor(), 0));
|
||||
EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(GetActor()));
|
||||
|
||||
EXPECT_TRUE(commandManager.Undo(result));
|
||||
EXPECT_EQ(5, CountSimulatedJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(5, CountSimulatedJoints(GetActor(), 0));
|
||||
EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(GetActor()));
|
||||
}
|
||||
|
||||
TEST_F(SimulatedObjectCommandTests, SimulatedObjectCommands_UndoRemoveJointTest)
|
||||
@@ -172,35 +172,35 @@ namespace EMotionFX
|
||||
CommandSystem::CommandManager commandManager;
|
||||
MCore::CommandGroup commandGroup;
|
||||
|
||||
const uint32 actorId = m_actor->GetID();
|
||||
const uint32 actorId = GetActor()->GetID();
|
||||
const AZStd::vector<AZStd::string> jointNames = GetTestJointNames();
|
||||
|
||||
// 1. Add simulated object
|
||||
CommandSimulatedObjectHelpers::AddSimulatedObject(actorId, AZStd::nullopt, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
|
||||
const AZStd::string serializedBase = SerializeSimulatedObjectSetup(m_actor.get());
|
||||
const AZStd::string serializedBase = SerializeSimulatedObjectSetup(GetActor());
|
||||
const size_t simulatedObjectIndex = 0;
|
||||
|
||||
// 2. Add r_upLeg simulated joints
|
||||
const Skeleton* skeleton = m_actor->GetSkeleton();
|
||||
const Skeleton* skeleton = GetActor()->GetSkeleton();
|
||||
const size_t r_upLegIdx = skeleton->FindNodeByName("r_upLeg")->GetNodeIndex();
|
||||
const size_t r_loLegIdx = skeleton->FindNodeByName("r_loLeg")->GetNodeIndex();
|
||||
CommandSimulatedObjectHelpers::AddSimulatedJoints(actorId, { r_upLegIdx, r_loLegIdx }, 0, false);
|
||||
EXPECT_EQ(2, CountSimulatedJoints(m_actor.get(), 0));
|
||||
const AZStd::string serializedUpLeg = SerializeSimulatedObjectSetup(m_actor.get());
|
||||
EXPECT_EQ(2, CountSimulatedJoints(GetActor(), 0));
|
||||
const AZStd::string serializedUpLeg = SerializeSimulatedObjectSetup(GetActor());
|
||||
|
||||
// 3. Remove the r_loLeg simulated joint
|
||||
AZStd::vector<SimulatedJoint*> jointsToBeRemoved;
|
||||
commandGroup.RemoveAllCommands();
|
||||
CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actorId, { r_upLegIdx }, simulatedObjectIndex, true, &commandGroup);
|
||||
EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
|
||||
EXPECT_EQ(0, CountSimulatedJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(serializedBase, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(0, CountSimulatedJoints(GetActor(), 0));
|
||||
EXPECT_EQ(serializedBase, SerializeSimulatedObjectSetup(GetActor()));
|
||||
|
||||
// 4. Undo
|
||||
// This recreates r_loLeg and r_loLeg but won't add all other children recursively as only these two joints got aded in step 3.
|
||||
EXPECT_TRUE(commandManager.Undo(result));
|
||||
EXPECT_EQ(2, CountSimulatedJoints(m_actor.get(), 0));
|
||||
EXPECT_EQ(serializedUpLeg, SerializeSimulatedObjectSetup(m_actor.get()));
|
||||
EXPECT_EQ(2, CountSimulatedJoints(GetActor(), 0));
|
||||
EXPECT_EQ(serializedUpLeg, SerializeSimulatedObjectSetup(GetActor()));
|
||||
}
|
||||
} // namespace EMotionFX
|
||||
|
||||
@@ -22,17 +22,21 @@
|
||||
#include <Tests/UI/UIFixture.h>
|
||||
#include <Tests/TestAssetCode/SimpleActors.h>
|
||||
#include <Tests/TestAssetCode/ActorFactory.h>
|
||||
#include <Tests/TestAssetCode/TestActorAssets.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
using SimulatedObjectModelTestsFixture = UIFixture;
|
||||
TEST_F(SimulatedObjectModelTestsFixture, CanUndoAddSimulatedObjectAndSimulatedJointWithChildren)
|
||||
{
|
||||
AutoRegisteredActor actor = ActorFactory::CreateAndInit<SimpleJointChainActor>(3, "simulatedObjectModelTestActor");
|
||||
AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}");
|
||||
AZ::Data::Asset<Integration::ActorAsset> actorAsset =
|
||||
TestActorAssets::CreateActorAssetAndRegister<SimpleJointChainActor>(actorAssetId, 3, "simulatedObjectModelTestActor");
|
||||
const Actor* actor = actorAsset->GetActor();
|
||||
|
||||
EMotionFX::SimulatedObjectWidget* simulatedObjectWidget = static_cast<EMotionFX::SimulatedObjectWidget*>(EMStudio::GetPluginManager()->FindActivePlugin(EMotionFX::SimulatedObjectWidget::CLASS_ID));
|
||||
ASSERT_TRUE(simulatedObjectWidget) << "Simulated Object plugin not loaded";
|
||||
simulatedObjectWidget->ActorSelectionChanged(actor.get());
|
||||
simulatedObjectWidget->ActorSelectionChanged(actorAsset->GetActor());
|
||||
|
||||
SimulatedObjectModel* model = simulatedObjectWidget->GetSimulatedObjectModel();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace EMotionFX
|
||||
|
||||
TEST_F(SimulatedObjectSerializeTests, SerializeTest)
|
||||
{
|
||||
SimulatedObjectSetup* setup = m_actor->GetSimulatedObjectSetup().get();
|
||||
SimulatedObjectSetup* setup = GetActor()->GetSimulatedObjectSetup().get();
|
||||
|
||||
// Build some setup.
|
||||
SimulatedObject* object = setup->AddSimulatedObject();
|
||||
@@ -29,7 +29,7 @@ namespace EMotionFX
|
||||
object->SetGravityFactor(3.0f);
|
||||
object->SetStiffnessFactor(4.0f);
|
||||
const AZStd::vector<AZStd::string> jointNames = { "l_upArm", "l_loArm", "l_hand" };
|
||||
Skeleton* skeleton = m_actor->GetSkeleton();
|
||||
Skeleton* skeleton = GetActor()->GetSkeleton();
|
||||
for (const AZStd::string& name : jointNames)
|
||||
{
|
||||
size_t skeletonJointIndex;
|
||||
@@ -50,7 +50,7 @@ namespace EMotionFX
|
||||
object->GetSimulatedJoint(0)->SetPinned(true);
|
||||
|
||||
// Serialize it and deserialize it.
|
||||
const AZStd::string serialized = SerializeSimulatedObjectSetup(m_actor.get());
|
||||
const AZStd::string serialized = SerializeSimulatedObjectSetup(GetActor());
|
||||
AZStd::unique_ptr<SimulatedObjectSetup> loadedSetup(DeserializeSimulatedObjectSetup(serialized));
|
||||
|
||||
// Verify some of the contents of the deserialized version.
|
||||
|
||||
@@ -22,13 +22,13 @@ namespace EMotionFX
|
||||
void SetUp()
|
||||
{
|
||||
ActorFixture::SetUp();
|
||||
m_actor->AddLODLevel();
|
||||
GetActor()->AddLODLevel();
|
||||
DisableJointsForLOD(m_disabledJointNames, 1);
|
||||
}
|
||||
|
||||
void DisableJointsForLOD(const std::vector<std::string>& jointNames, size_t lodLevel)
|
||||
{
|
||||
const Skeleton* skeleton = m_actor->GetSkeleton();
|
||||
const Skeleton* skeleton = GetActor()->GetSkeleton();
|
||||
for (const std::string& jointName : jointNames)
|
||||
{
|
||||
Node* joint = skeleton->FindNodeByName(jointName.c_str());
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <EMotionFX/Source/Actor.h>
|
||||
#include <EMotionFX/Source/EMotionFXManager.h>
|
||||
#include <EMotionFX/Source/Importer/Importer.h>
|
||||
#include <Tests/TestAssetCode/TestActorAssets.h>
|
||||
#include <Tests/TestAssetCode/ActorFactory.h>
|
||||
#include <Tests/TestAssetCode/JackActor.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user