Merge remote-tracking branch 'upstream/stabilization/2106' into santorac/stabilization/2106/HotReloadFixes

main
Santora 5 years ago
commit a09ddb1b89

@ -105,24 +105,25 @@ endforeach()
# Post-processing
################################################################################
# The following steps have to be done after all targets are registered:
# Defer generation of the StaticModules.inl file which is needed to create the AZ::Module derived class in monolithic
# builds until after all the targets are known
ly_delayed_generate_static_modules_inl()
# 1. Add any dependencies registered via ly_enable_gems
ly_enable_gems_delayed()
# 2. generate a settings registry .setreg file for all ly_add_project_dependencies() and ly_add_target_dependencies() calls
# 2. Defer generation of the StaticModules.inl file which is needed to create the AZ::Module derived class in monolithic
# builds until after all the targets are known and all the gems are enabled
ly_delayed_generate_static_modules_inl()
# 3. generate a settings registry .setreg file for all ly_add_project_dependencies() and ly_add_target_dependencies() calls
# to provide applications with the filenames of gem modules to load
# This must be done before ly_delayed_target_link_libraries() as that inserts BUILD_DEPENDENCIES as MANUALLY_ADDED_DEPENDENCIES
# if the build dependency is a MODULE_LIBRARY. That would cause a false load dependency to be generated
ly_delayed_generate_settings_registry()
# 3. link targets where the dependency was yet not declared, we need to have the declaration so we do different
# 4. link targets where the dependency was yet not declared, we need to have the declaration so we do different
# linking logic depending on the type of target
ly_delayed_target_link_libraries()
# 4. generate a registry file for unit testing for platforms that support unit testing
# 5. generate a registry file for unit testing for platforms that support unit testing
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_delayed_generate_unit_test_module_registry()
endif()

@ -292,8 +292,13 @@ namespace AZ
const typename VecType::FloatType cmp2 = VecType::AndNot(cmp0, cmp1);
// -1/x
// this step is calculated for all values of x, but only used if x > Sqrt(2) + 1
// in order to avoid a division by zero, detect if xabs is zero here and replace it with an arbitrary value
// if xabs does equal zero, the value here doesn't matter because the result will be thrown away
typename VecType::FloatType xabsSafe =
VecType::Add(xabs, VecType::And(VecType::CmpEq(xabs, VecType::ZeroFloat()), FastLoadConstant<VecType>(Simd::g_vec1111)));
const typename VecType::FloatType y0 = VecType::And(cmp0, FastLoadConstant<VecType>(Simd::g_HalfPi));
typename VecType::FloatType x0 = VecType::Div(FastLoadConstant<VecType>(Simd::g_vec1111), xabs);
typename VecType::FloatType x0 = VecType::Div(FastLoadConstant<VecType>(Simd::g_vec1111), xabsSafe);
x0 = VecType::Xor(x0, VecType::CastToFloat(FastLoadConstant<VecType>(Simd::g_negateMask)));
const typename VecType::FloatType y1 = VecType::And(cmp2, FastLoadConstant<VecType>(Simd::g_QuarterPi));
@ -368,8 +373,12 @@ namespace AZ
typename VecType::FloatType offset = VecType::And(x_lt_0, offset1);
// the result of this part of the computation is thrown away if x equals 0,
// but if x does equal 0, it will cause a division by zero
// so replace zero by an arbitrary value here in that case
typename VecType::FloatType xSafe = VecType::Add(x, VecType::And(x_eq_0, FastLoadConstant<VecType>(Simd::g_vec1111)));
const typename VecType::FloatType atan_mask = VecType::Not(VecType::Or(x_eq_0, y_eq_0));
const typename VecType::FloatType atan_arg = VecType::Div(y, x);
const typename VecType::FloatType atan_arg = VecType::Div(y, xSafe);
typename VecType::FloatType atan_result = VecType::Atan(atan_arg);
atan_result = VecType::Add(atan_result, offset);
atan_result = VecType::AndNot(pio2_mask, atan_result);

@ -471,6 +471,7 @@ namespace AZ
AZ_MATH_INLINE Vec2::FloatType Vec2::Reciprocal(FloatArgType value)
{
value = Sse::ReplaceFourth(Sse::ReplaceThird(value, 1.0f), 1.0f);
return Sse::Reciprocal(value);
}
@ -513,6 +514,7 @@ namespace AZ
AZ_MATH_INLINE Vec2::FloatType Vec2::SqrtInv(FloatArgType value)
{
value = Sse::ReplaceFourth(Sse::ReplaceThird(value, 1.0f), 1.0f);
return Sse::SqrtInv(value);
}

@ -507,6 +507,7 @@ namespace AZ
AZ_MATH_INLINE Vec3::FloatType Vec3::Reciprocal(FloatArgType value)
{
value = Sse::ReplaceFourth(value, 1.0f);
return Sse::Reciprocal(value);
}
@ -549,6 +550,7 @@ namespace AZ
AZ_MATH_INLINE Vec3::FloatType Vec3::SqrtInv(FloatArgType value)
{
value = Sse::ReplaceFourth(value, 1.0f);
return Sse::SqrtInv(value);
}

@ -8,25 +8,27 @@
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/AzTest/Platform/${PAL_PLATFORM_NAME})
ly_add_target(
NAME AzTest STATIC
NAMESPACE AZ
FILES_CMAKE
AzTest/aztest_files.cmake
${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
INCLUDE_DIRECTORIES
PUBLIC
.
${pal_dir}
BUILD_DEPENDENCIES
PUBLIC
3rdParty::googletest::GMock
3rdParty::googletest::GTest
3rdParty::GoogleBenchmark
AZ::AzCore
PLATFORM_INCLUDE_FILES
if(NOT LY_MONOLITHIC_GAME)
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/AzTest/Platform/${PAL_PLATFORM_NAME})
ly_add_target(
NAME AzTest STATIC
NAMESPACE AZ
FILES_CMAKE
AzTest/aztest_files.cmake
${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
INCLUDE_DIRECTORIES
PUBLIC
.
${pal_dir}
BUILD_DEPENDENCIES
PUBLIC
3rdParty::googletest::GMock
3rdParty::googletest::GTest
3rdParty::GoogleBenchmark
AZ::AzCore
PLATFORM_INCLUDE_FILES
${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake
)
)
endif()

@ -252,13 +252,20 @@ namespace AzToolsFramework
}
AZStd::string out;
if (m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out))
if (!m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out))
{
const size_t bytesToWrite = out.size();
const size_t bytesWritten = stream.Write(bytesToWrite, out.data());
return bytesWritten == bytesToWrite;
return false;
}
return false;
const size_t bytesToWrite = out.size();
const size_t bytesWritten = stream.Write(bytesToWrite, out.data());
if(bytesWritten != bytesToWrite)
{
return false;
}
m_prefabSystemComponent->SetTemplateDirtyFlag(templateId, false);
return true;
}
void PrefabEditorEntityOwnershipService::CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename)

@ -58,8 +58,17 @@ namespace AzToolsFramework
if (!path.empty())
{
infoString =
QObject::tr("<span style=\"font-style: italic; font-weight: 400;\">(%1)</span>").arg(path.Filename().Native().data());
QString saveFlag = "";
auto dirtyOutcome = m_prefabPublicInterface->HasUnsavedChanges(path);
if (dirtyOutcome.IsSuccess() && dirtyOutcome.GetValue() == true)
{
saveFlag = "*";
}
infoString = QObject::tr("<span style=\"font-style: italic; font-weight: 400;\">(%1%2)</span>")
.arg(path.Filename().Native().data())
.arg(saveFlag);
}
return infoString;

@ -196,6 +196,16 @@ function(ly_delayed_generate_static_modules_inl)
ly_get_gem_load_dependencies(all_game_gem_dependencies ${project_name}.GameLauncher)
foreach(game_gem_dependency ${all_game_gem_dependencies})
# Sometimes, a gem's Client variant may be an interface library
# which dependes on multiple gem targets. The interface libraries
# should be skipped; the real dependencies of the interface will be processed
if(TARGET ${game_gem_dependency})
get_target_property(target_type ${game_gem_dependency} TYPE)
if(${target_type} STREQUAL "INTERFACE_LIBRARY")
continue()
endif()
endif()
# To match the convention on how gems targets vs gem modules are named,
# we remove the ".Static" from the suffix
# Replace "." with "_"
@ -224,6 +234,14 @@ function(ly_delayed_generate_static_modules_inl)
list(APPEND all_server_gem_dependencies ${server_gem_load_dependencies} ${server_gem_dependency})
endforeach()
foreach(server_gem_dependency ${all_server_gem_dependencies})
# Skip interface libraries
if(TARGET ${server_gem_dependency})
get_target_property(target_type ${server_gem_dependency} TYPE)
if(${target_type} STREQUAL "INTERFACE_LIBRARY")
continue()
endif()
endif()
# Replace "." with "_"
string(REPLACE "." "_" server_gem_dependency ${server_gem_dependency})

@ -13,7 +13,7 @@ ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${P
include(${pal_dir}/platform_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
if(PAL_TRAIT_AZTESTRUNNER_SUPPORTED)
if(PAL_TRAIT_AZTESTRUNNER_SUPPORTED AND NOT LY_MONOLITHIC_GAME)
ly_add_target(
NAME AzTestRunner ${PAL_TRAIT_AZTESTRUNNER_LAUNCHER_TYPE}

@ -177,9 +177,10 @@ namespace AZ
AZ::Entity* rootEntity = reinterpret_cast<AZ::Entity*>(classPtr);
bool convertResult = ConvertSliceToPrefab(context, outputPath, isDryRun, rootEntity);
// Clear out the references to any nested slices so that the nested assets get unloaded correctly at the end of
// the conversion.
ClearSliceAssetReferences(rootEntity);
// Delete the root entity pointer. Otherwise, it will leak itself along with all of the slice asset references held
// within it.
delete rootEntity;
return convertResult;
};
@ -229,8 +230,12 @@ namespace AZ
return false;
}
// Get all of the entities from the slice.
// Get all of the entities from the slice. We're taking ownership of them, so we also remove them from the slice component
// without deleting them.
constexpr bool deleteEntities = false;
constexpr bool removeEmptyInstances = true;
SliceComponent::EntityList sliceEntities = sliceComponent->GetNewEntities();
sliceComponent->RemoveAllEntities(deleteEntities, removeEmptyInstances);
AZ_Printf("Convert-Slice", " Slice contains %zu entities.\n", sliceEntities.size());
// Create the Prefab with the entities from the slice.
@ -273,6 +278,12 @@ namespace AZ
}
}
// Save off a mapping of the slice's metadata entity ID as well, even though we never converted the entity itself.
// This will help us better detect entity ID mapping errors for nested slice instances.
AZ::Entity* metadataEntity = sliceComponent->GetMetadataEntity();
constexpr bool isMetadataEntity = true;
m_aliasIdMapper.emplace(metadataEntity->GetId(), SliceEntityMappingInfo(templateId, "MetadataEntity", isMetadataEntity));
// Update the prefab template with the fixed-up data in our prefab instance.
AzToolsFramework::Prefab::PrefabDom prefabDom;
bool storeResult = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*sourceInstance, prefabDom);
@ -402,6 +413,21 @@ namespace AZ
"Convert-Slice", " Attaching %zu instances of nested slice '%s'.\n", instances.size(),
nestedPrefabPath.Native().c_str());
// Before processing any further, save off all the known entity IDs from all the instances and how they map back to
// the base nested prefab that they've come from (i.e. this one). As we proceed up the chain of nesting, this will
// build out a hierarchical list of owning instances for each entity that we can trace upwards to know where to add
// the entity into our nested prefab instance.
// This step needs to occur *before* converting the instances themselves, because while converting instances, they
// might have entity ID references that point to other instances. By having the full instance entity ID map in place
// before conversion, we'll be able to fix them up appropriately.
for (auto& instance : instances)
{
AZStd::string instanceAlias = GetInstanceAlias(instance);
UpdateSliceEntityInstanceMappings(instance.GetEntityIdToBaseMap(), instanceAlias);
}
// Now that we have all the entity ID mappings, convert all the instances.
for (auto& instance : instances)
{
bool instanceConvertResult = ConvertSliceInstance(instance, sliceAsset, nestedTemplate, sourceInstance);
@ -415,6 +441,28 @@ namespace AZ
return true;
}
AZStd::string SliceConverter::GetInstanceAlias(const AZ::SliceComponent::SliceInstance& instance)
{
// When creating the new instance, we would like to have deterministic instance aliases. Prefabs that depend on this one
// will have patches that reference the alias, so if we reconvert this slice a second time, we would like it to produce
// the same results. To get a deterministic and unique alias, we rely on the slice instance. The slice instance contains
// a map of slice entity IDs to unique instance entity IDs. We'll just consistently use the first entry in the map as the
// unique instance ID.
AZStd::string instanceAlias;
auto entityIdMap = instance.GetEntityIdMap();
if (!entityIdMap.empty())
{
instanceAlias = AZStd::string::format("Instance_%s", entityIdMap.begin()->second.ToString().c_str());
}
else
{
AZ_Error("Convert-Slice", false, " Couldn't create deterministic instance alias.");
instanceAlias = AZStd::string::format("Instance_%s", AZ::Entity::MakeId().ToString().c_str());
}
return instanceAlias;
}
bool SliceConverter::ConvertSliceInstance(
AZ::SliceComponent::SliceInstance& instance,
AZ::Data::Asset<AZ::SliceAsset>& sliceAsset,
@ -438,27 +486,7 @@ namespace AZ
auto instanceToTemplateInterface = AZ::Interface<AzToolsFramework::Prefab::InstanceToTemplateInterface>::Get();
auto prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
// When creating the new instance, we would like to have deterministic instance aliases. Prefabs that depend on this one
// will have patches that reference the alias, so if we reconvert this slice a second time, we would like it to produce
// the same results. To get a deterministic and unique alias, we rely on the slice instance. The slice instance contains
// a map of slice entity IDs to unique instance entity IDs. We'll just consistently use the first entry in the map as the
// unique instance ID.
AZStd::string instanceAlias;
auto entityIdMap = instance.GetEntityIdMap();
if (!entityIdMap.empty())
{
instanceAlias = AZStd::string::format("Instance_%s", entityIdMap.begin()->second.ToString().c_str());
}
else
{
instanceAlias = AZStd::string::format("Instance_%s", AZ::Entity::MakeId().ToString().c_str());
}
// Before processing any further, save off all the known entity IDs from this instance and how they map back to the base
// nested prefab that they've come from (i.e. this one). As we proceed up the chain of nesting, this will build out a
// hierarchical list of owning instances for each entity that we can trace upwards to know where to add the entity into
// our nested prefab instance.
UpdateSliceEntityInstanceMappings(instance.GetEntityIdToBaseMap(), instanceAlias);
AZStd::string instanceAlias = GetInstanceAlias(instance);
// Create a new unmodified prefab Instance for the nested slice instance.
auto nestedInstance = AZStd::make_unique<AzToolsFramework::Prefab::Instance>();
@ -619,6 +647,10 @@ namespace AZ
SetParentEntity(containerEntity->get(), topLevelInstance->GetContainerEntityId(), onlySetIfInvalid);
}
// After doing all of the above, run through entity references in any of the patched entities, and fix up the entity IDs to
// match the new ones in our prefabs.
RemapIdReferences(m_aliasIdMapper, topLevelInstance, nestedInstance.get(), instantiated, dependentSlice->GetSerializeContext());
// Add the nested instance itself to the top-level prefab. To do this, we need to add it to our top-level instance,
// create a patch out of it, and patch the top-level prefab template.
@ -750,17 +782,6 @@ namespace AZ
AZ_Error("Convert-Slice", disconnected, "Asset Processor failed to disconnect successfully.");
}
void SliceConverter::ClearSliceAssetReferences(AZ::Entity* rootEntity)
{
SliceComponent* sliceComponent = AZ::EntityUtils::FindFirstDerivedComponent<SliceComponent>(rootEntity);
// Make a copy of the slice list and remove all of them from the loaded component.
AZ::SliceComponent::SliceList slices = sliceComponent->GetSlices();
for (auto& slice : slices)
{
sliceComponent->RemoveSlice(&slice);
}
}
void SliceConverter::UpdateSliceEntityInstanceMappings(
const AZ::SliceComponent::EntityIdToEntityIdMap& sliceEntityIdMap, const AZStd::string& currentInstanceAlias)
{
@ -789,9 +810,108 @@ namespace AZ
AZ_Assert(oldId == newId, "The same entity instance ID has unexpectedly appeared twice in the same nested prefab.");
}
}
else
{
AZ_Warning("Convert-Slice", false, " Couldn't find an entity ID conversion for %s.", oldId.ToString().c_str());
}
}
}
void SliceConverter::RemapIdReferences(
const AZStd::unordered_map<AZ::EntityId, SliceEntityMappingInfo>& idMapper,
AzToolsFramework::Prefab::Instance* topLevelInstance,
AzToolsFramework::Prefab::Instance* nestedInstance,
SliceComponent::InstantiatedContainer* instantiatedEntities,
SerializeContext* context)
{
// Given a set of instantiated entities, run through all of them, look for entity references, and replace the entity IDs with
// new ones that match up with our prefabs.
IdUtils::Remapper<EntityId>::ReplaceIdsAndIdRefs(
instantiatedEntities,
[idMapper, &topLevelInstance, &nestedInstance](
const EntityId& sourceId, bool isEntityId, [[maybe_unused]] const AZStd::function<EntityId()>& idGenerator) -> EntityId
{
EntityId newId = sourceId;
// Only convert valid entity references. Actual entity IDs have already been taken care of elsewhere, so ignore them.
if (!isEntityId && sourceId.IsValid())
{
auto entityEntry = idMapper.find(sourceId);
// Since we've already remapped transform hierarchies to include container entities, it's possible that our entity
// reference is pointing to a container, which means it won't be in our slice mapping table. In that case, just
// return it as-is.
if (entityEntry == idMapper.end())
{
return sourceId;
}
// We've got a slice->prefab mapping entry, so now we need to use it.
auto& mappingStruct = entityEntry->second;
if (mappingStruct.m_nestedInstanceAliases.empty())
{
// If we don't have a chain of nested instance aliases, then this entity reference is either within the
// current nested instance or it's pointing to an entity in the top-level instance. We'll try them both
// to look for a match.
EntityId prefabId = nestedInstance->GetEntityId(mappingStruct.m_entityAlias);
if (!prefabId.IsValid())
{
prefabId = topLevelInstance->GetEntityId(mappingStruct.m_entityAlias);
}
if (prefabId.IsValid())
{
newId = prefabId;
}
else
{
AZ_Error("Convert-Slice", false, " Couldn't find source ID %s", sourceId.ToString().c_str());
}
}
else
{
// We *do* have a chain of nested instance aliases. This chain could either be relative to the nested instance
// or the top-level instance. We can tell which one it is by which one can find the first nested instance
// alias.
AzToolsFramework::Prefab::Instance* entityInstance = nestedInstance;
auto it = mappingStruct.m_nestedInstanceAliases.rbegin();
if (!entityInstance->FindNestedInstance(*it).has_value())
{
entityInstance = topLevelInstance;
}
// Now that we've got a starting point, iterate through the chain of nested instance aliases to find the
// correct instance to get the entity ID for. We have to go from slice IDs -> entity aliases -> entity IDs
// because prefab instance creation can change some of our entity IDs along the way.
for (; it != mappingStruct.m_nestedInstanceAliases.rend(); it++)
{
auto foundInstance = entityInstance->FindNestedInstance(*it);
if (foundInstance.has_value())
{
entityInstance = &(foundInstance->get());
}
else
{
AZ_Assert(false, "Couldn't find nested instance %s", it->c_str());
}
}
EntityId prefabId = entityInstance->GetEntityId(mappingStruct.m_entityAlias);
if (prefabId.IsValid())
{
newId = prefabId;
}
}
}
return newId;
},
context);
}
} // namespace SerializeContextTools
} // namespace AZ

@ -42,6 +42,28 @@ namespace AZ
bool ConvertSliceFiles(Application& application);
private:
// When converting slice entities, especially for nested slices, we need to keep track of the original
// entity ID, the entity alias it uses in the prefab, and which template and nested instance path it maps to.
// As we encounter each instanced entity ID, we can look it up in this structure and use this to determine how to properly
// add it to the correct place in the hierarchy.
struct SliceEntityMappingInfo
{
SliceEntityMappingInfo(
AzToolsFramework::Prefab::TemplateId templateId,
AzToolsFramework::Prefab::EntityAlias entityAlias,
bool isMetadataEntity = false)
: m_templateId(templateId)
, m_entityAlias(entityAlias)
, m_isMetadataEntity(isMetadataEntity)
{
}
AzToolsFramework::Prefab::TemplateId m_templateId;
AzToolsFramework::Prefab::EntityAlias m_entityAlias;
AZStd::vector<AzToolsFramework::Prefab::InstanceAlias> m_nestedInstanceAliases;
bool m_isMetadataEntity{ false };
};
bool ConnectToAssetProcessor();
void DisconnectFromAssetProcessor();
@ -58,27 +80,17 @@ namespace AZ
void SetParentEntity(const AZ::Entity& entity, const AZ::EntityId& parentId, bool onlySetIfInvalid);
void PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId);
bool SavePrefab(AZ::IO::PathView outputPath, AzToolsFramework::Prefab::TemplateId templateId);
void ClearSliceAssetReferences(AZ::Entity* rootEntity);
void UpdateSliceEntityInstanceMappings(
const AZ::SliceComponent::EntityIdToEntityIdMap& sliceEntityIdMap,
const AZStd::string& currentInstanceAlias);
AZStd::string GetInstanceAlias(const AZ::SliceComponent::SliceInstance& instance);
// When converting slice entities, especially for nested slices, we need to keep track of the original
// entity ID, the entity alias it uses in the prefab, and which template and nested instance path it maps to.
// As we encounter each instanced entity ID, we can look it up in this structure and use this to determine how to properly
// add it to the correct place in the hierarchy.
struct SliceEntityMappingInfo
{
SliceEntityMappingInfo(AzToolsFramework::Prefab::TemplateId templateId, AzToolsFramework::Prefab::EntityAlias entityAlias)
: m_templateId(templateId)
, m_entityAlias(entityAlias)
{
}
AzToolsFramework::Prefab::TemplateId m_templateId;
AzToolsFramework::Prefab::EntityAlias m_entityAlias;
AZStd::vector<AzToolsFramework::Prefab::InstanceAlias> m_nestedInstanceAliases;
};
void RemapIdReferences(
const AZStd::unordered_map<AZ::EntityId, SliceEntityMappingInfo>& idMapper,
AzToolsFramework::Prefab::Instance* topLevelInstance,
AzToolsFramework::Prefab::Instance* nestedInstance,
SliceComponent::InstantiatedContainer* instantiatedEntities,
SerializeContext* context);
// Track all of the entity IDs created and associate them with enough conversion information to know how to place the
// entities in the correct place in the prefab hierarchy and fix up parent entity ID mappings to work with the nested

@ -8,7 +8,7 @@
"$type": "DX12::PlatformLimitsDescriptor",
"m_descriptorHeapLimits": {
"DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV": [16384, 262144],
"DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV": [1000000, 1000000],
"DESCRIPTOR_HEAP_TYPE_SAMPLER": [2048, 2048],
"DESCRIPTOR_HEAP_TYPE_RTV": [2048, 0],
"DESCRIPTOR_HEAP_TYPE_DSV": [2048, 0]

@ -23,7 +23,9 @@ namespace AZ
{
Low,
Medium,
High
High,
Count
};
//! This class provides general features and configuration for the diffuse global illumination environment,

@ -43,6 +43,12 @@ namespace AZ
void DiffuseGlobalIlluminationFeatureProcessor::SetQualityLevel(DiffuseGlobalIlluminationQualityLevel qualityLevel)
{
if (qualityLevel >= DiffuseGlobalIlluminationQualityLevel::Count)
{
AZ_Assert(false, "SetQualityLevel called with invalid quality level [%d]", qualityLevel);
return;
}
m_qualityLevel = qualityLevel;
UpdatePasses();

@ -118,8 +118,7 @@ namespace AZ
void EditorAttachmentComponent::Activate()
{
Base::Activate();
m_boneFollower.Activate(GetEntity(), CreateAttachmentConfiguration(),
false); // Entity's don't animate in Editor
m_boneFollower.Activate(GetEntity(), CreateAttachmentConfiguration(), /*targetCanAnimate=*/true);
}
void EditorAttachmentComponent::Deactivate()

@ -29,7 +29,7 @@ namespace AZ
static void Reflect(ReflectContext* context);
DiffuseGlobalIlluminationQualityLevel m_qualityLevel;
DiffuseGlobalIlluminationQualityLevel m_qualityLevel = DiffuseGlobalIlluminationQualityLevel::Low;
};
}
}

@ -36,7 +36,7 @@ namespace AZ
->Attribute(Edit::Attributes::Category, "Atom")
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZStd::vector<AZ::Crc32>({ AZ_CRC("Level", 0x9aeacc13), AZ_CRC("Game", 0x232b318c) }))
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZStd::vector<AZ::Crc32>({ AZ_CRC("Level", 0x9aeacc13) }))
->Attribute(Edit::Attributes::AutoExpand, true)
->Attribute(Edit::Attributes::HelpPageURL, "https://")
;

@ -20,10 +20,12 @@ namespace CommandSystem
SelectionList::SelectionList()
{
EMotionFX::ActorNotificationBus::Handler::BusConnect();
EMotionFX::ActorInstanceNotificationBus::Handler::BusConnect();
}
SelectionList::~SelectionList()
{
EMotionFX::ActorInstanceNotificationBus::Handler::BusDisconnect();
EMotionFX::ActorNotificationBus::Handler::BusDisconnect();
}
@ -378,4 +380,9 @@ namespace CommandSystem
RemoveActor(actor);
}
void SelectionList::OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance)
{
RemoveActorInstance(actorInstance);
}
} // namespace CommandSystem

@ -15,6 +15,7 @@
#include "CommandSystemConfig.h"
#include <EMotionFX/Source/ActorBus.h>
#include <EMotionFX/Source/ActorInstance.h>
#include <EMotionFX/Source/ActorInstanceBus.h>
#include <EMotionFX/Source/Motion.h>
#include <EMotionFX/Source/Node.h>
#include <EMotionFX/Source/MotionInstance.h>
@ -27,7 +28,8 @@ namespace CommandSystem
* specific time stamp in a scene.
*/
class COMMANDSYSTEM_API SelectionList
: EMotionFX::ActorNotificationBus::Handler
: private EMotionFX::ActorNotificationBus::Handler
, private EMotionFX::ActorInstanceNotificationBus::Handler
{
MCORE_MEMORYOBJECTCATEGORY(SelectionList, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_COMMANDSYSTEM);
@ -400,6 +402,9 @@ namespace CommandSystem
// ActorNotificationBus overrides
void OnActorDestroyed(EMotionFX::Actor* actor) override;
// ActorInstanceNotificationBus overrides
void OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) override;
AZStd::vector<EMotionFX::Node*> mSelectedNodes; /**< Array of selected nodes. */
AZStd::vector<EMotionFX::Actor*> mSelectedActors; /**< The selected actors. */
AZStd::vector<EMotionFX::ActorInstance*> mSelectedActorInstances; /**< Array of selected actor instances. */

@ -34,6 +34,7 @@
#include "NodeGroup.h"
#include "Recorder.h"
#include "TransformData.h"
#include <EMotionFX/Source/ActorInstanceBus.h>
#include <EMotionFX/Source/DebugDraw.h>
#include <EMotionFX/Source/RagdollInstance.h>
@ -153,20 +154,14 @@ namespace EMotionFX
// register it
GetActorManager().RegisterActorInstance(this);
// automatically register the actor instance
GetEventManager().OnCreateActorInstance(this);
GetActorManager().GetScheduler()->RecursiveInsertActorInstance(this);
ActorInstanceNotificationBus::Broadcast(&ActorInstanceNotificationBus::Events::OnActorInstanceCreated, this);
}
// the destructor
ActorInstance::~ActorInstance()
{
// trigger the OnDeleteActorInstance event
GetEventManager().OnDeleteActorInstance(this);
// remove it from the recording
GetRecorder().RemoveActorInstanceFromRecording(this);
ActorInstanceNotificationBus::Broadcast(&ActorInstanceNotificationBus::Events::OnActorInstanceDestroyed, this);
// get rid of the motion system
if (mMotionSystem)

@ -0,0 +1,54 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
namespace EMotionFX
{
class ActorInstance;
/**
* EMotion FX Actor Instance Request Bus
* Used for making requests to actor instances.
*/
class ActorInstanceRequests
: public AZ::EBusTraits
{
public:
};
using ActorInstanceRequestBus = AZ::EBus<ActorInstanceRequests>;
/**
* EMotion FX Actor Instance Notification Bus
* Used for monitoring events from actor instances.
*/
class ActorInstanceNotifications
: public AZ::EBusTraits
{
public:
// Enable multi-threaded access by locking primitive using a mutex when connecting handlers to the EBus or executing events.
using MutexType = AZStd::recursive_mutex;
virtual void OnActorInstanceCreated([[maybe_unused]] ActorInstance* actorInstance) {}
/**
* Called when any of the actor instances gets destructed.
* @param actorInstance The actorInstance that gets destructed.
*/
virtual void OnActorInstanceDestroyed([[maybe_unused]] ActorInstance* actorInstance) {}
};
using ActorInstanceNotificationBus = AZ::EBus<ActorInstanceNotifications>;
} // namespace EMotionFX

@ -51,7 +51,6 @@ namespace EMotionFX
EVENT_TYPE_MOTION_INSTANCE_LAST_EVENT = EVENT_TYPE_ON_QUEUE_MOTION_INSTANCE,
EVENT_TYPE_ON_DELETE_ACTOR,
EVENT_TYPE_ON_DELETE_ACTOR_INSTANCE,
EVENT_TYPE_ON_SIMULATE_PHYSICS,
EVENT_TYPE_ON_CUSTOM_EVENT,
EVENT_TYPE_ON_DRAW_LINE,
@ -64,7 +63,6 @@ namespace EMotionFX
EVENT_TYPE_ON_CREATE_MOTION_INSTANCE,
EVENT_TYPE_ON_CREATE_MOTION_SYSTEM,
EVENT_TYPE_ON_CREATE_ACTOR,
EVENT_TYPE_ON_CREATE_ACTOR_INSTANCE,
EVENT_TYPE_ON_POST_CREATE_ACTOR,
EVENT_TYPE_ON_DELETE_ANIM_GRAPH,
EVENT_TYPE_ON_DELETE_ANIM_GRAPH_INSTANCE,
@ -298,15 +296,6 @@ namespace EMotionFX
*/
virtual void OnDeleteActor(Actor* actor) { MCORE_UNUSED(actor); }
/**
* The event that gets triggered once an ActorInstance object is being deleted.
* You could for example use this event to delete any allocations you have done inside the
* custom user data object linked with the ActorInstance object.
* You can get and set this data object with the ActorInstance::GetCustomData() and ActorInstance::SetCustomData(...) methods.
* @param actorInstance The actorInstance that is being deleted.
*/
virtual void OnDeleteActorInstance(ActorInstance* actorInstance) { MCORE_UNUSED(actorInstance); }
virtual void OnSimulatePhysics(float timeDelta) { MCORE_UNUSED(timeDelta); }
virtual void OnCustomEvent(uint32 eventType, void* data) { MCORE_UNUSED(eventType); MCORE_UNUSED(data); }
@ -321,7 +310,6 @@ namespace EMotionFX
virtual void OnCreateMotionInstance(MotionInstance* motionInstance) { MCORE_UNUSED(motionInstance); }
virtual void OnCreateMotionSystem(MotionSystem* motionSystem) { MCORE_UNUSED(motionSystem); }
virtual void OnCreateActor(Actor* actor) { MCORE_UNUSED(actor); }
virtual void OnCreateActorInstance(ActorInstance* actorInstance) { MCORE_UNUSED(actorInstance); }
virtual void OnPostCreateActor(Actor* actor) { MCORE_UNUSED(actor); }
// delete callbacks

@ -305,16 +305,6 @@ namespace EMotionFX
}
void EventManager::OnDeleteActorInstance(ActorInstance* actorInstance)
{
const EventHandlerVector& eventHandlers = m_eventHandlersByEventType[EVENT_TYPE_ON_DELETE_ACTOR_INSTANCE];
for (EventHandler* eventHandler : eventHandlers)
{
eventHandler->OnDeleteActorInstance(actorInstance);
}
}
// draw a debug triangle
void EventManager::OnDrawTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color)
{
@ -670,17 +660,6 @@ namespace EMotionFX
}
// create an actor instance
void EventManager::OnCreateActorInstance(ActorInstance* actorInstance)
{
const EventHandlerVector& eventHandlers = m_eventHandlersByEventType[EVENT_TYPE_ON_CREATE_ACTOR_INSTANCE];
for (EventHandler* eventHandler : eventHandlers)
{
eventHandler->OnCreateActorInstance(actorInstance);
}
}
// on post create actor
void EventManager::OnPostCreateActor(Actor* actor)
{

@ -286,15 +286,6 @@ namespace EMotionFX
*/
void OnDeleteActor(Actor* actor);
/**
* The event that gets triggered once an ActorInstance object is being deleted.
* You could for example use this event to delete any allocations you have done inside the
* custom user data object linked with the ActorInstance object.
* You can get and set this data object with the ActorInstance::GetCustomData() and ActorInstance::SetCustomData(...) methods.
* @param actorInstance The actorInstance that is being deleted.
*/
void OnDeleteActorInstance(ActorInstance* actorInstance);
void OnSimulatePhysics(float timeDelta);
void OnCustomEvent(uint32 eventType, void* data);
void OnDrawTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color);
@ -343,7 +334,6 @@ namespace EMotionFX
void OnCreateMotionInstance(MotionInstance* motionInstance);
void OnCreateMotionSystem(MotionSystem* motionSystem);
void OnCreateActor(Actor* actor);
void OnCreateActorInstance(ActorInstance* actorInstance);
void OnPostCreateActor(Actor* actor);
// delete callbacks

@ -106,16 +106,12 @@ namespace EMotionFX
mCurrentPlayTime = 0.0f;
mObjects.SetMemoryCategory(EMFX_MEMCATEGORY_RECORDER);
GetEMotionFX().GetEventManager()->AddEventHandler(this);
EMotionFX::ActorInstanceNotificationBus::Handler::BusConnect();
}
Recorder::~Recorder()
{
if (EventManager* eventManager = GetEMotionFX().GetEventManager())
{
eventManager->RemoveEventHandler(this);
}
EMotionFX::ActorInstanceNotificationBus::Handler::BusDisconnect();
Clear();
}
@ -1448,7 +1444,7 @@ namespace EMotionFX
Unlock();
}
void Recorder::OnDeleteActorInstance(ActorInstance* actorInstance)
void Recorder::OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance)
{
// Actor instances created by actor components do not use the command system and don't call a ClearRecorder command.
// Thus, these actor instances will have to be removed from the recorder to avoid dangling data.

@ -23,6 +23,7 @@
#include <MCore/Source/File.h>
#include <MCore/Source/Vector.h>
#include <MCore/Source/MultiThreadManager.h>
#include <EMotionFX/Source/ActorInstanceBus.h>
#include <EMotionFX/Source/AnimGraphObjectIds.h>
#include <EMotionFX/Source/EventHandler.h>
#include <EMotionFX/Source/EventInfo.h>
@ -47,7 +48,7 @@ namespace EMotionFX
class EMFX_API Recorder
: public BaseObject
, public EventHandler
, private EMotionFX::ActorInstanceNotificationBus::Handler
{
public:
AZ_CLASS_ALLOCATOR_DECL
@ -319,9 +320,8 @@ namespace EMotionFX
void RemoveActorInstanceFromRecording(ActorInstance* actorInstance);
void RemoveAnimGraphFromRecording(AnimGraph* animGraph);
// EventHandler overrides
const AZStd::vector<EventTypes> GetHandledEventTypes() const override { return {EMotionFX::EVENT_TYPE_ON_DELETE_ACTOR_INSTANCE}; }
void OnDeleteActorInstance(ActorInstance* actorInstance) override;
// ActorInstanceNotificationBus overrides
void OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) override;
void SampleAndApplyTransforms(float timeInSeconds, ActorInstance* actorInstance) const;
void SampleAndApplyMainTransform(float timeInSeconds, ActorInstance* actorInstance) const;

@ -17,25 +17,26 @@
#include "../../../../EMStudioSDK/Source/EMStudioCore.h"
#include <MCore/Source/LogManager.h>
#include <EMotionFX/CommandSystem/Source/CommandManager.h>
#include <EMotionFX/Source/ActorManager.h>
#include <EMotionFX/Source/MorphSetup.h>
#include "../../../../EMStudioSDK/Source/EMStudioManager.h"
namespace EMStudio
{
// constructor
MorphTargetsWindowPlugin::MorphTargetsWindowPlugin()
: EMStudio::DockWidgetPlugin()
{
mDialogStack = nullptr;
mCurrentActorInstance = nullptr;
mDialogStack = nullptr;
mCurrentActorInstance = nullptr;
mStaticTextWidget = nullptr;
}
EMotionFX::ActorInstanceNotificationBus::Handler::BusConnect();
}
// destructor
MorphTargetsWindowPlugin::~MorphTargetsWindowPlugin()
{
EMotionFX::ActorInstanceNotificationBus::Handler::BusDisconnect();
// unregister the command callbacks and get rid of the memory
for (auto callback : m_callbacks)
{
@ -110,14 +111,16 @@ namespace EMStudio
mMorphTargetGroups.clear();
}
// reinit the morph target dialog, e.g. if selection changes
void MorphTargetsWindowPlugin::ReInit(bool forceReInit)
{
// get the selected actorinstance
const CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection();
EMotionFX::ActorInstance* actorInstance = selection.GetSingleActorInstance();
const CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection();
EMotionFX::ActorInstance* actorInstance = selection.GetSingleActorInstance();
ReInit(actorInstance, forceReInit);
}
void MorphTargetsWindowPlugin::ReInit(EMotionFX::ActorInstance* actorInstance, bool forceReInit)
{
// show hint if no/multiple actor instances is/are selected
if (actorInstance == nullptr)
{
@ -135,10 +138,7 @@ namespace EMStudio
return;
}
// get our selected actor instance and the corresponding actor
EMotionFX::Actor* actor = actorInstance->GetActor();
// only reinit the morph targets if actorinstance changed
// only reinit the morph targets if actor instance changed
if (mCurrentActorInstance != actorInstance || forceReInit)
{
// set the current actor instance in any case
@ -150,7 +150,7 @@ namespace EMStudio
AZStd::vector<EMotionFX::MorphSetupInstance::MorphTarget*> phonemeInstances;
AZStd::vector<EMotionFX::MorphSetupInstance::MorphTarget*> defaultMorphTargetInstances;
// get the morph target setup
EMotionFX::Actor* actor = actorInstance->GetActor();
EMotionFX::MorphSetup* morphSetup = actor->GetMorphSetup(actorInstance->GetLODLevel());
if (morphSetup == nullptr)
{
@ -278,6 +278,13 @@ namespace EMStudio
}
}
void MorphTargetsWindowPlugin::OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance)
{
if (mCurrentActorInstance == actorInstance)
{
ReInit(/*actorInstance=*/nullptr);
}
}
//-----------------------------------------------------------------------------------------
// Command callbacks

@ -16,6 +16,7 @@
#include <MysticQt/Source/DialogStack.h>
#include "../../../../EMStudioSDK/Source/DockWidgetPlugin.h"
#include <EMotionFX/CommandSystem/Source/SelectionCommands.h>
#include <EMotionFX/Source/ActorInstanceBus.h>
#include "MorphTargetGroupWidget.h"
#include <QVBoxLayout>
#include <QLabel>
@ -26,6 +27,7 @@ namespace EMStudio
{
class MorphTargetsWindowPlugin
: public EMStudio::DockWidgetPlugin
, private EMotionFX::ActorInstanceNotificationBus::Handler
{
Q_OBJECT
MCORE_MEMORYOBJECTCATEGORY(MorphTargetsWindowPlugin, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS);
@ -54,6 +56,7 @@ namespace EMStudio
EMStudioPlugin* Clone() override;
// update the morph targets window based on the current selection
void ReInit(EMotionFX::ActorInstance* actorInstance, bool forceReInit = false);
void ReInit(bool forceReInit = false);
// clear all widgets from the window
@ -70,6 +73,9 @@ namespace EMStudio
void WindowReInit(bool visible);
private:
// ActorInstanceNotificationBus overrides
void OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) override;
// declare the callbacks
MCORE_DEFINECOMMANDCALLBACK(CommandSelectCallback);
MCORE_DEFINECOMMANDCALLBACK(CommandUnselectCallback);

@ -15,6 +15,7 @@ set(FILES
Source/ActorBus.h
Source/ActorInstance.cpp
Source/ActorInstance.h
Source/ActorInstanceBus.h
Source/ActorManager.cpp
Source/ActorManager.h
Source/ActorUpdateScheduler.h

@ -24,6 +24,7 @@ ly_set(PAL_TRAIT_BUILD_CPACK_SUPPORTED FALSE)
# Test library support
ly_set(PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED FALSE)
ly_set(PAL_TRAIT_TEST_GOOGLE_BENCHMARK_SUPPORTED FALSE)
ly_set(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED FALSE)
ly_set(PAL_TRAIT_TEST_PYTEST_SUPPORTED FALSE)
ly_set(PAL_TRAIT_TEST_TARGET_TYPE MODULE)

@ -24,6 +24,7 @@ ly_set(PAL_TRAIT_BUILD_CPACK_SUPPORTED FALSE)
# Test library support
ly_set(PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED TRUE)
ly_set(PAL_TRAIT_TEST_GOOGLE_BENCHMARK_SUPPORTED TRUE)
ly_set(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED FALSE)
ly_set(PAL_TRAIT_TEST_PYTEST_SUPPORTED TRUE)
ly_set(PAL_TRAIT_TEST_TARGET_TYPE MODULE)

@ -24,6 +24,7 @@ ly_set(PAL_TRAIT_BUILD_CPACK_SUPPORTED FALSE)
# Test library support
ly_set(PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED TRUE)
ly_set(PAL_TRAIT_TEST_GOOGLE_BENCHMARK_SUPPORTED TRUE)
ly_set(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED TRUE)
ly_set(PAL_TRAIT_TEST_PYTEST_SUPPORTED FALSE)
ly_set(PAL_TRAIT_TEST_TARGET_TYPE MODULE)

@ -24,6 +24,7 @@ ly_set(PAL_TRAIT_BUILD_CPACK_SUPPORTED TRUE)
# Test library support
ly_set(PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED TRUE)
ly_set(PAL_TRAIT_TEST_GOOGLE_BENCHMARK_SUPPORTED TRUE)
ly_set(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED TRUE)
ly_set(PAL_TRAIT_TEST_PYTEST_SUPPORTED TRUE)
ly_set(PAL_TRAIT_TEST_TARGET_TYPE MODULE)

@ -22,6 +22,8 @@
<bal:WixStandardBootstrapperApplication
LicenseUrl="$(var.CPACK_LICENSE_URL)"
LogoFile="$(var.CPACK_WIX_PRODUCT_LOGO)"
ThemeFile="$(var.CPACK_BOOTSTRAP_THEME_FILE).xml"
LocalizationFile="$(var.CPACK_BOOTSTRAP_THEME_FILE).wxl"
ShowVersion="yes" />
</BootstrapperApplicationRef>
<?else?>
@ -29,6 +31,8 @@
<bal:WixStandardBootstrapperApplication
LicenseFile="$(var.CPACK_WIX_LICENSE_RTF)"
LogoFile="$(var.CPACK_WIX_PRODUCT_LOGO)"
ThemeFile="$(var.CPACK_BOOTSTRAP_THEME_FILE).xml"
LocalizationFile="$(var.CPACK_BOOTSTRAP_THEME_FILE).wxl"
ShowVersion="yes" />
</BootstrapperApplicationRef>
<?endif?>

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<WixLocalization Culture="en-us"
Language="1033"
xmlns="http://schemas.microsoft.com/wix/2006/localization">
<!-- common -->
<String Id="WindowTitle">[WixBundleName] Setup</String>
<String Id="Title">[WixBundleName]</String>
<String Id="InstallVersion">Version [WixBundleVersion]</String>
<String Id="ConfirmCancelMessage">Are you sure you want to cancel?</String>
<!-- welcome page -->
<String Id="InstallHeader">Welcome</String>
<String Id="InstallMessage">
Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit.
</String>
<String Id="InstallLicenseLinkText">[WixBundleName] &lt;a href="#"&gt;license terms&lt;/a&gt;.</String>
<String Id="InstallAcceptCheckbox">I &amp;agree to the license terms and conditions</String>
<String Id="InstallOptionsButton">&amp;Options</String>
<String Id="InstallInstallButton">&amp;Install</String>
<String Id="InstallCloseButton">&amp;Close</String>
<!-- configure install page -->
<String Id="OptionsHeader">Setup Options</String>
<String Id="OptionsLocationLabel">Install location:</String>
<String Id="OptionsBrowseButton">&amp;Browse</String>
<String Id="OptionsOkButton">&amp;OK</String>
<String Id="OptionsCancelButton">&amp;Cancel</String>
<!-- edit existing install page -->
<String Id="ModifyHeader">Modify Setup</String>
<String Id="ModifyRepairButton">&amp;Repair</String>
<String Id="ModifyUninstallButton">&amp;Uninstall</String>
<String Id="ModifyCloseButton">&amp;Close</String>
<!-- action progress page -->
<String Id="ProgressHeader">Setup Progress</String>
<String Id="ProgressLabel">Processing:</String>
<String Id="OverallProgressPackageText">Initializing...</String>
<String Id="ProgressCancelButton">&amp;Cancel</String>
<!-- final page (success state) -->
<String Id="SuccessHeader">Setup Successful</String>
<String Id="SuccessInstallHeader">Installation Successfully Completed</String>
<String Id="SuccessRepairHeader">Repair Successfully Completed</String>
<String Id="SuccessUninstallHeader">Uninstall Successfully Completed</String>
<String Id="SuccessLaunchButton">&amp;Launch</String>
<String Id="SuccessCloseButton">&amp;Close</String>
<!-- final page (fail state) -->
<String Id="FailureHeader">Setup Failed</String>
<String Id="FailureInstallHeader">Setup Failed</String>
<String Id="FailureUninstallHeader">Uninstall Failed</String>
<String Id="FailureRepairHeader">Repair Failed</String>
<String Id="FailureHyperlinkLogText">
One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href="#"&gt;log file&lt;/a&gt;.
</String>
<String Id="FailureCloseButton">&amp;Close</String>
<!-- help page -->
<String Id="HelpHeader">Setup Help</String>
<String Id="HelpText">
/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or creates a complete local copy of the bundle in directory. Install is the default.
/passive | /quiet - displays minimal UI with no prompts or displays no UI and no prompts. By default UI and all prompts are displayed.
/log log.txt - logs to a specific file. By default a log file is created in %TEMP%.
</String>
<String Id="HelpCloseButton">&amp;Close</String>
</WixLocalization>

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<Theme xmlns="http://wixtoolset.org/schemas/thmutil/2010">
<Window Width="485" Height="300" HexStyle="100a0000" FontId="0">#(loc.WindowTitle)</Window>
<Font Id="0" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<Font Id="1" Height="-24" Weight="500" Foreground="000000">Segoe UI</Font>
<Font Id="2" Height="-22" Weight="500" Foreground="666666">Segoe UI</Font>
<Font Id="3" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<!-- top banner -->
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" Visible="yes"/>
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" Visible="yes" DisablePrefix="yes">#(loc.Title)</Text>
<!-- welcome page -->
<Page Name="Install">
@WIX_THEME_INSTALL_LICENSE_ELEMENT@
<Checkbox Name="EulaAcceptCheckbox" X="-11" Y="-41" Width="260" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>
<Button Name="OptionsButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.InstallOptionsButton)</Button>
<Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
<Button Name="WelcomeCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>
</Page>
<!-- configure install page -->
<Page Name="Options">
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.OptionsHeader)</Text>
<Text X="11" Y="121" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OptionsLocationLabel)</Text>
<Editbox Name="FolderEditbox" X="11" Y="143" Width="-91" Height="21" TabStop="yes" FontId="3" FileSystemAutoComplete="yes" />
<Button Name="BrowseButton" X="-11" Y="142" Width="75" Height="23" TabStop="yes" FontId="3">#(loc.OptionsBrowseButton)</Button>
<Button Name="OptionsOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.OptionsOkButton)</Button>
<Button Name="OptionsCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.OptionsCancelButton)</Button>
</Page>
<!-- edit existing install page -->
<Page Name="Modify">
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Text>
<Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button>
<Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button>
<Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyCloseButton)</Button>
</Page>
<!-- action progress page -->
<Page Name="Progress">
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Text>
<Text X="11" Y="121" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Text>
<Text Name="OverallProgressPackageText" X="85" Y="121" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Text>
<Progressbar Name="OverallCalculatedProgressbar" X="11" Y="143" Width="-11" Height="15" />
<Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>
</Page>
<!-- final page (success state) -->
<Page Name="Success">
<Text Name="SuccessHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessHeader)</Text>
<Text Name="SuccessInstallHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessInstallHeader)</Text>
<Text Name="SuccessRepairHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRepairHeader)</Text>
<Text Name="SuccessUninstallHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessUninstallHeader)</Text>
<Button Name="LaunchButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button>
<Button Name="SuccessCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.SuccessCloseButton)</Button>
</Page>
<!-- final page (failure state) -->
<Page Name="Failure">
<Text Name="FailureHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureHeader)</Text>
<Text Name="FailureInstallHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureInstallHeader)</Text>
<Text Name="FailureUninstallHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureUninstallHeader)</Text>
<Text Name="FailureRepairHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRepairHeader)</Text>
<Hypertext Name="FailureLogFileLink" X="11" Y="121" Width="-11" Height="42" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext>
<Hypertext Name="FailureMessageText" X="22" Y="163" Width="-11" Height="51" FontId="3" TabStop="yes" HideWhenDisabled="yes" />
<Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FailureCloseButton)</Button>
</Page>
<!-- help page -->
<Page Name="Help">
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Text>
<Text X="11" Y="112" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Text>
<Button Name="HelpCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.HelpCloseButton)</Button>
</Page>
</Theme>

@ -25,6 +25,7 @@ set(_ext_flags
)
set(_addtional_defines
-dCPACK_BOOTSTRAP_THEME_FILE=${CPACK_BINARY_DIR}/BootstrapperTheme
-dCPACK_BOOTSTRAP_UPGRADE_GUID=${CPACK_WIX_BOOTSTRAP_UPGRADE_GUID}
-dCPACK_DOWNLOAD_SITE=${CPACK_DOWNLOAD_SITE}
-dCPACK_LOCAL_INSTALLER_DIR=${_cpack_wix_out_dir}

@ -92,6 +92,28 @@ set(CPACK_WIX_EXTENSIONS
set(_embed_artifacts "yes")
if(LY_INSTALLER_DOWNLOAD_URL)
if(LY_INSTALLER_LICENSE_URL)
set(WIX_THEME_INSTALL_LICENSE_ELEMENT
"<Hypertext Name=\"EulaHyperlink\" X=\"11\" Y=\"121\" Width=\"-11\" Height=\"51\" TabStop=\"yes\" FontId=\"3\" HideWhenDisabled=\"yes\">#(loc.InstallLicenseLinkText)</Hypertext>"
)
else()
set(WIX_THEME_INSTALL_LICENSE_ELEMENT
"<Richedit Name=\"EulaRichedit\" X=\"11\" Y=\"80\" Width=\"-11\" Height=\"-70\" TabStop=\"yes\" FontId=\"0\" HexStyle=\"0x800000\" />"
)
endif()
configure_file(
"${CPACK_SOURCE_DIR}/Platform/Windows/Packaging/BootstrapperTheme.xml.in"
"${CPACK_BINARY_DIR}/BootstrapperTheme.xml"
@ONLY
)
configure_file(
"${CPACK_SOURCE_DIR}/Platform/Windows/Packaging/BootstrapperTheme.wxl.in"
"${CPACK_BINARY_DIR}/BootstrapperTheme.wxl"
@ONLY
)
set(_embed_artifacts "no")
# the bootstrapper will at the very least need a different upgrade guid

@ -26,6 +26,8 @@ set(FILES
Packaging_windows.cmake
PackagingPostBuild.cmake
Packaging/Bootstrapper.wxs
Packaging/BootstrapperTheme.wxl.in
Packaging/BootstrapperTheme.xml.in
Packaging/Shortcuts.wxs
Packaging/Template.wxs.in
)

@ -24,6 +24,7 @@ ly_set(PAL_TRAIT_BUILD_CPACK_SUPPORTED FALSE)
# Test library support
ly_set(PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED FALSE)
ly_set(PAL_TRAIT_TEST_GOOGLE_BENCHMARK_SUPPORTED FALSE)
ly_set(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED FALSE)
ly_set(PAL_TRAIT_TEST_PYTEST_SUPPORTED FALSE)
ly_set(PAL_TRAIT_TEST_TARGET_TYPE MODULE)

@ -20,20 +20,22 @@ endif()
# Tests
################################################################################
foreach(suite_name ${LY_TEST_GLOBAL_KNOWN_SUITE_NAMES})
ly_add_pytest(
NAME pytest_sanity_${suite_name}_no_gpu
PATH ${CMAKE_CURRENT_LIST_DIR}/sanity_test.py
TEST_SUITE ${suite_name}
)
ly_add_pytest(
NAME pytest_sanity_${suite_name}_requires_gpu
PATH ${CMAKE_CURRENT_LIST_DIR}/sanity_test.py
TEST_SUITE ${suite_name}
TEST_REQUIRES gpu
)
endforeach()
if(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED)
foreach(suite_name ${LY_TEST_GLOBAL_KNOWN_SUITE_NAMES})
ly_add_pytest(
NAME pytest_sanity_${suite_name}_no_gpu
PATH ${CMAKE_CURRENT_LIST_DIR}/sanity_test.py
TEST_SUITE ${suite_name}
)
ly_add_pytest(
NAME pytest_sanity_${suite_name}_requires_gpu
PATH ${CMAKE_CURRENT_LIST_DIR}/sanity_test.py
TEST_SUITE ${suite_name}
TEST_REQUIRES gpu
)
endforeach()
endif()
# EPB Sanity test is being registered here to validate that the ly_add_editor_python_test function works.
#if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedTesting IN_LIST LY_PROJECTS_TARGET_NAME)

Loading…
Cancel
Save