Merge branch 'stabilization/2106' into non-uniform-scale-migration
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Helpers Icon</title>
|
||||
<defs>
|
||||
<circle id="path-1" cx="8" cy="8" r="8"></circle>
|
||||
<path d="M8.59736328,10.1821289 L8.59736328,9.79394531 C8.59736328,9.07617188 8.86835937,8.71728516 9.84248047,8.15332031 C10.8751953,7.54541016 11.4098633,6.77636719 11.4098633,5.67041016 C11.4098633,4.00048828 10.0255859,2.8359375 7.93085937,2.8359375 C5.68232422,2.8359375 4.40791016,4.09570312 4.37128906,5.89746094 L6.35615234,5.89746094 C6.40009766,5.06982422 6.95673828,4.53515625 7.79902344,4.53515625 C8.63398437,4.53515625 9.190625,5.04052734 9.190625,5.73632812 C9.190625,6.43212891 8.90498047,6.79101562 7.96015625,7.35498047 C6.94941406,7.94824219 6.54658203,8.60742188 6.64179687,9.75732422 L6.65644531,10.1821289 L8.59736328,10.1821289 Z M7.70380859,13.7124023 C8.52412109,13.7124023 9.02949219,13.2436523 9.02949219,12.4892578 C9.02949219,11.7275391 8.52412109,11.2587891 7.70380859,11.2587891 C6.88349609,11.2587891 6.37080078,11.7275391 6.37080078,12.4892578 C6.37080078,13.2436523 6.88349609,13.7124023 7.70380859,13.7124023 Z" id="path-3"></path>
|
||||
</defs>
|
||||
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="2nd-ToolBar-v2-(Perspective)-3" transform="translate(-1161.000000, -7.000000)">
|
||||
<g id="2nd-ToolBar-buttons-on-right" transform="translate(1076.000000, 5.000000)">
|
||||
<g id="Helpers-Icon" transform="translate(85.000000, 2.000000)">
|
||||
<mask id="mask-2" fill="white">
|
||||
<use xlink:href="#path-1"></use>
|
||||
</mask>
|
||||
<use id="Oval" fill="#FFFFFF" xlink:href="#path-1"></use>
|
||||
<g id="?" fill-rule="nonzero" mask="url(#mask-2)">
|
||||
<use fill="#909090" xlink:href="#path-3"></use>
|
||||
<use fill="#3F3F3F" xlink:href="#path-3"></use>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -29,5 +29,6 @@
|
||||
<file alias="trackview_editor.svg">Menu/trackview_editor.svg</file>
|
||||
<file alias="ui_editor.svg">Menu/ui_editor.svg</file>
|
||||
<file alias="menu.svg">Menu/menu.svg</file>
|
||||
<file alias="helpers.svg">Menu/helpers.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -130,6 +130,7 @@ CViewportTitleDlg::CViewportTitleDlg(QWidget* pParent)
|
||||
SetupCameraDropdownMenu();
|
||||
SetupResolutionDropdownMenu();
|
||||
SetupViewportInformationMenu();
|
||||
SetupHelpersButton();
|
||||
SetupOverflowMenu();
|
||||
|
||||
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, gSettings.bMuteAudio ? m_oMuteAudioRequest : m_oUnmuteAudioRequest);
|
||||
@@ -211,15 +212,16 @@ void CViewportTitleDlg::SetupViewportInformationMenu()
|
||||
|
||||
}
|
||||
|
||||
void CViewportTitleDlg::SetupHelpersButton()
|
||||
{
|
||||
connect(m_ui->m_helpers, &QToolButton::clicked, this, &CViewportTitleDlg::OnToggleHelpers);
|
||||
m_ui->m_helpers->setChecked(Helpers::IsHelpersShown());
|
||||
}
|
||||
|
||||
void CViewportTitleDlg::SetupOverflowMenu()
|
||||
{
|
||||
// Setup the overflow menu
|
||||
QMenu* overFlowMenu = new QMenu(this);
|
||||
m_debugHelpersAction = new QAction("Debug Helpers", overFlowMenu);
|
||||
m_debugHelpersAction->setCheckable(true);
|
||||
m_debugHelpersAction->setChecked(Helpers::IsHelpersShown());
|
||||
connect(m_debugHelpersAction, &QAction::triggered, this, &CViewportTitleDlg::OnToggleHelpers);
|
||||
overFlowMenu->addAction(m_debugHelpersAction);
|
||||
|
||||
m_audioMuteAction = new QAction("Mute Audio", overFlowMenu);
|
||||
connect(m_audioMuteAction, &QAction::triggered, this, &CViewportTitleDlg::OnBnClickedMuteAudio);
|
||||
@@ -333,7 +335,7 @@ void CViewportTitleDlg::OnMaximize()
|
||||
void CViewportTitleDlg::OnToggleHelpers()
|
||||
{
|
||||
Helpers::ToggleHelpers();
|
||||
m_debugHelpersAction->setChecked(Helpers::IsHelpersShown());
|
||||
m_ui->m_helpers->setChecked(Helpers::IsHelpersShown());
|
||||
}
|
||||
|
||||
void CViewportTitleDlg::SetNoViewportInfo()
|
||||
@@ -759,7 +761,7 @@ void CViewportTitleDlg::OnEditorNotifyEvent(EEditorNotifyEvent event)
|
||||
switch (event)
|
||||
{
|
||||
case eNotify_OnDisplayRenderUpdate:
|
||||
m_debugHelpersAction->setChecked(Helpers::IsHelpersShown());
|
||||
m_ui->m_helpers->setChecked(Helpers::IsHelpersShown());
|
||||
break;
|
||||
case eNotify_OnBeginGameMode:
|
||||
case eNotify_OnEndGameMode:
|
||||
|
||||
@@ -102,6 +102,7 @@ protected:
|
||||
void SetupResolutionDropdownMenu();
|
||||
void SetupViewportInformationMenu();
|
||||
void SetupOverflowMenu();
|
||||
void SetupHelpersButton();
|
||||
|
||||
QString m_title;
|
||||
|
||||
@@ -172,7 +173,6 @@ protected:
|
||||
QAction* m_normalInformationAction = nullptr;
|
||||
QAction* m_fullInformationAction = nullptr;
|
||||
QAction* m_compactInformationAction = nullptr;
|
||||
QAction* m_debugHelpersAction = nullptr;
|
||||
QAction* m_audioMuteAction = nullptr;
|
||||
QAction* m_enableVRAction = nullptr;
|
||||
QAction* m_enableGridSnappingAction = nullptr;
|
||||
|
||||
@@ -81,6 +81,18 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_helpers">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/Menu/helpers.svg</normaloff>:/Menu/helpers.svg
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_resolutionMenu">
|
||||
<property name="icon">
|
||||
|
||||
@@ -255,7 +255,6 @@ namespace AZ
|
||||
{
|
||||
return AZStd::make_pair(animation, anim);
|
||||
}
|
||||
|
||||
Events::ProcessingResult AssImpAnimationImporter::ImportAnimation(AssImpSceneNodeAppendedContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", "Animation");
|
||||
@@ -447,7 +446,22 @@ namespace AZ
|
||||
|
||||
return combinedAnimationResult.GetResult();
|
||||
}
|
||||
decltype(boneAnimations) parentFillerAnimations;
|
||||
|
||||
AZStd::unordered_set<AZStd::string> boneList;
|
||||
|
||||
for (int meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
|
||||
{
|
||||
aiMesh* mesh = scene->mMeshes[meshIndex];
|
||||
|
||||
for (int boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex)
|
||||
{
|
||||
aiBone* bone = mesh->mBones[boneIndex];
|
||||
|
||||
boneList.insert(bone->mName.C_Str());
|
||||
}
|
||||
}
|
||||
|
||||
decltype(boneAnimations) fillerAnimations;
|
||||
|
||||
// Go through all the animations and make sure we create animations for bones who's parents don't have an animation
|
||||
for (auto&& anim : boneAnimations)
|
||||
@@ -459,8 +473,8 @@ namespace AZ
|
||||
{
|
||||
if (!IsPivotNode(parent->mName))
|
||||
{
|
||||
if (boneAnimations.find(parent->mName.C_Str()) == boneAnimations.end() &&
|
||||
parentFillerAnimations.find(parent->mName.C_Str()) == parentFillerAnimations.end())
|
||||
if (!boneAnimations.contains(parent->mName.C_Str()) &&
|
||||
!fillerAnimations.contains(parent->mName.C_Str()))
|
||||
{
|
||||
// Create 1 key for each type that just copies the current transform
|
||||
ConsolidatedNodeAnim emptyAnimation;
|
||||
@@ -472,7 +486,7 @@ namespace AZ
|
||||
globalTransform.Decompose(scale, rotation, position);
|
||||
|
||||
emptyAnimation.mNumRotationKeys = emptyAnimation.mNumPositionKeys = emptyAnimation.mNumScalingKeys = 1;
|
||||
|
||||
|
||||
emptyAnimation.m_ownedPositionKeys.emplace_back(0, position);
|
||||
emptyAnimation.mPositionKeys = emptyAnimation.m_ownedPositionKeys.data();
|
||||
|
||||
@@ -481,9 +495,9 @@ namespace AZ
|
||||
|
||||
emptyAnimation.m_ownedScalingKeys.emplace_back(0, scale);
|
||||
emptyAnimation.mScalingKeys = emptyAnimation.m_ownedScalingKeys.data();
|
||||
|
||||
parentFillerAnimations.insert(
|
||||
AZStd::make_pair(parent->mName.C_Str(), AZStd::make_pair(anim.second.first, AZStd::move(emptyAnimation))));
|
||||
|
||||
fillerAnimations.insert(AZStd::make_pair(
|
||||
parent->mName.C_Str(), AZStd::make_pair(anim.second.first, AZStd::move(emptyAnimation))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,7 +505,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
boneAnimations.insert(AZStd::make_move_iterator(parentFillerAnimations.begin()), AZStd::make_move_iterator(parentFillerAnimations.end()));
|
||||
boneAnimations.insert(AZStd::make_move_iterator(fillerAnimations.begin()), AZStd::make_move_iterator(fillerAnimations.end()));
|
||||
|
||||
auto animItr = boneAnimations.equal_range(currentNode->mName.C_Str());
|
||||
|
||||
|
||||
@@ -98,6 +98,20 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
aiMatrix4x4 CalculateWorldTransform(const aiNode* currentNode)
|
||||
{
|
||||
aiMatrix4x4 transform = {};
|
||||
const aiNode* iteratingNode = currentNode;
|
||||
|
||||
while (iteratingNode)
|
||||
{
|
||||
transform = iteratingNode->mTransformation * transform;
|
||||
iteratingNode = iteratingNode->mParent;
|
||||
}
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
Events::ProcessingResult AssImpBoneImporter::ImportBone(AssImpNodeEncounteredContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", "Bone");
|
||||
@@ -111,12 +125,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
bool isBone = false;
|
||||
|
||||
if (NodeParentIsOfType(context.m_scene.GetGraph(), context.m_currentGraphPosition, DataTypes::IBoneData::TYPEINFO_Uuid()))
|
||||
{
|
||||
isBone = true;
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
AZStd::unordered_map<AZStd::string, const aiNode*> mainBoneList;
|
||||
AZStd::unordered_map<AZStd::string, const aiBone*> boneLookup;
|
||||
@@ -170,15 +179,8 @@ namespace AZ
|
||||
{
|
||||
createdBoneData = AZStd::make_shared<SceneData::GraphData::RootBoneData>();
|
||||
}
|
||||
|
||||
aiMatrix4x4 transform = currentNode->mTransformation;
|
||||
const aiNode* parent = currentNode->mParent;
|
||||
|
||||
while (parent)
|
||||
{
|
||||
transform = parent->mTransformation * transform;
|
||||
parent = parent->mParent;
|
||||
}
|
||||
aiMatrix4x4 transform = CalculateWorldTransform(currentNode);
|
||||
|
||||
SceneAPI::DataTypes::MatrixType globalTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(transform);
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace AZ
|
||||
~AssImpBoneImporter() override = default;
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
|
||||
Events::ProcessingResult ImportBone(AssImpNodeEncounteredContext& context);
|
||||
};
|
||||
} // namespace FbxSceneBuilder
|
||||
|
||||
@@ -46,8 +46,9 @@ namespace AZ
|
||||
serializeContext->Class<AssImpTransformImporter, SceneCore::LoadingComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
void GetAllBones(const aiScene* scene, AZStd::unordered_map<AZStd::string, const aiBone*>& boneLookup)
|
||||
|
||||
void GetAllBones(
|
||||
const aiScene* scene, AZStd::unordered_multimap<AZStd::string, const aiBone*>& boneLookup)
|
||||
{
|
||||
for (unsigned meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
|
||||
{
|
||||
@@ -57,7 +58,7 @@ namespace AZ
|
||||
{
|
||||
const aiBone* bone = mesh->mBones[boneIndex];
|
||||
|
||||
boneLookup[bone->mName.C_Str()] = bone;
|
||||
boneLookup.emplace(bone->mName.C_Str(), bone);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,41 +74,53 @@ namespace AZ
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
AZStd::unordered_map<AZStd::string, const aiBone*> boneLookup;
|
||||
AZStd::unordered_multimap<AZStd::string, const aiBone*> boneLookup;
|
||||
GetAllBones(scene, boneLookup);
|
||||
|
||||
auto boneIterator = boneLookup.find(currentNode->mName.C_Str());
|
||||
const bool isBone = boneIterator != boneLookup.end();
|
||||
|
||||
aiMatrix4x4 combinedTransform;
|
||||
|
||||
DataTypes::MatrixType localTransform;
|
||||
|
||||
if (isBone)
|
||||
{
|
||||
auto parentNode = currentNode->mParent;
|
||||
AZStd::vector<DataTypes::MatrixType> offsets, inverseOffsets;
|
||||
auto iteratingNode = currentNode;
|
||||
|
||||
aiMatrix4x4 offsetMatrix = boneIterator->second->mOffsetMatrix;
|
||||
aiMatrix4x4 parentOffset {};
|
||||
|
||||
auto parentBoneIterator = boneLookup.find(parentNode->mName.C_Str());
|
||||
|
||||
if (parentNode && parentBoneIterator != boneLookup.end())
|
||||
while (iteratingNode && boneLookup.count(iteratingNode->mName.C_Str()))
|
||||
{
|
||||
const auto& parentBone = parentBoneIterator->second;
|
||||
AZStd::string name = iteratingNode->mName.C_Str();
|
||||
|
||||
parentOffset = parentBone->mOffsetMatrix;
|
||||
auto range = boneLookup.equal_range(name);
|
||||
|
||||
if (range.first != range.second)
|
||||
{
|
||||
// There can be multiple offsetMatrices for a given bone, we're only interested in grabbing the first one
|
||||
auto boneFirstOffsetMatrix = range.first->second->mOffsetMatrix;
|
||||
auto azMat = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(boneFirstOffsetMatrix);
|
||||
offsets.push_back(azMat);
|
||||
inverseOffsets.push_back(azMat.GetInverseFull());
|
||||
}
|
||||
|
||||
iteratingNode = iteratingNode->mParent;
|
||||
}
|
||||
|
||||
auto inverseOffset = offsetMatrix;
|
||||
inverseOffset.Inverse();
|
||||
|
||||
combinedTransform = parentOffset * inverseOffset;
|
||||
|
||||
localTransform =
|
||||
offsets.at(AZ::GetMin(offsets.size()-1, static_cast<decltype(offsets.size())>(1))) // parent bone offset, or if there is no parent, then current node offset
|
||||
* inverseOffsets.at(inverseOffsets.size() - 1) // Inverse of root bone offset
|
||||
* offsets.at(offsets.size() - 1) // Root bone offset
|
||||
* inverseOffsets.at(0); // Inverse of current node offset
|
||||
}
|
||||
else
|
||||
{
|
||||
combinedTransform = GetConcatenatedLocalTransform(currentNode);
|
||||
localTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(GetConcatenatedLocalTransform(currentNode));
|
||||
}
|
||||
|
||||
DataTypes::MatrixType localTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(combinedTransform);
|
||||
// Don't bother adding a node with the identity matrix
|
||||
if (localTransform == DataTypes::MatrixType::Identity())
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
context.m_sourceSceneSystem.SwapTransformForUpAxis(localTransform);
|
||||
context.m_sourceSceneSystem.ConvertUnit(localTransform);
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace AZ
|
||||
{
|
||||
if (inputPropertyValue.IsObject() && inputPropertyValue.HasMember("Value") && inputPropertyValue.HasMember("$type"))
|
||||
{
|
||||
// Requiring explicit type info to differentiate be=tween colors versus vectors and numeric types
|
||||
// Requiring explicit type info to differentiate between colors versus vectors and numeric types
|
||||
const AZ::Uuid baseTypeId = azrtti_typeid<T>();
|
||||
AZ::Uuid typeId = AZ::Uuid::CreateNull();
|
||||
result.Combine(LoadTypeId(typeId, inputPropertyValue, context, &baseTypeId));
|
||||
@@ -198,7 +198,7 @@ namespace AZ
|
||||
{
|
||||
outputPropertyValue.SetObject();
|
||||
|
||||
// Storing explicit type info to differentiate be=tween colors versus vectors and numeric types
|
||||
// Storing explicit type info to differentiate between colors versus vectors and numeric types
|
||||
rapidjson::Value typeValue;
|
||||
result.Combine(StoreTypeId(typeValue, azrtti_typeid<T>(), context));
|
||||
outputPropertyValue.AddMember("$type", typeValue, context.GetJsonAllocator());
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
// AZ
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/containers/map.h>
|
||||
|
||||
// Graph Model
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
// AZ
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/any.h>
|
||||
#include <AzCore/std/smart_ptr/enable_shared_from_this.h>
|
||||
|
||||
// Graph Model
|
||||
#include <GraphModel/Integration/GraphCanvasMetadata.h>
|
||||
#include <GraphModel/Model/Common.h>
|
||||
#include <GraphModel/Model/GraphElement.h>
|
||||
|
||||
@@ -136,9 +136,9 @@ namespace GraphModel
|
||||
//! Set/gets a bundle of generic metadata that is provided by the node graph UI
|
||||
//! system. This may include node positions, comment blocks, node groupings, and
|
||||
//! bookmarks, for example.
|
||||
void SetUiMetadata(const AZStd::any& uiMetadata);
|
||||
const AZStd::any& GetUiMetadata() const;
|
||||
AZStd::any& GetUiMetadata();
|
||||
void SetUiMetadata(const GraphModelIntegration::GraphCanvasMetadata& uiMetadata);
|
||||
const GraphModelIntegration::GraphCanvasMetadata& GetUiMetadata() const;
|
||||
GraphModelIntegration::GraphCanvasMetadata& GetUiMetadata();
|
||||
|
||||
AZStd::shared_ptr<Slot> FindSlot(const Endpoint& endpoint);
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace GraphModel
|
||||
ConnectionList m_connections;
|
||||
|
||||
//! Used to store and serialize metadata from the graph UI, like node positions, comments, group boxes, etc.
|
||||
AZStd::any m_uiMetadata;
|
||||
GraphModelIntegration::GraphCanvasMetadata m_uiMetadata;
|
||||
|
||||
//! Used to store all of our node <-> wrapper node mappings
|
||||
NodeWrappingMap m_nodeWrappings;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#pragma once
|
||||
|
||||
// AZ
|
||||
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
|
||||
#include <AzCore/std/any.h>
|
||||
#include <AzCore/std/hash.h>
|
||||
#include <AzCore/std/containers/list.h>
|
||||
@@ -165,6 +166,32 @@ namespace GraphModel
|
||||
ExtendableSlotConfiguration m_extendableSlotConfiguration;
|
||||
};
|
||||
|
||||
//! Custom JSON serializer for Slot because we use an AZStd::any for m_value
|
||||
class JsonSlotSerializer
|
||||
: public AZ::BaseJsonSerializer
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(JsonSlotSerializer, "{8AC96D70-7BCD-4D68-8813-269938982D51}", AZ::BaseJsonSerializer);
|
||||
AZ_CLASS_ALLOCATOR(JsonSlotSerializer, AZ::SystemAllocator, 0);
|
||||
|
||||
AZ::JsonSerializationResult::Result Load(
|
||||
void* outputValue, const AZ::Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
|
||||
AZ::JsonDeserializerContext& context) override;
|
||||
|
||||
AZ::JsonSerializationResult::Result Store(
|
||||
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const AZ::Uuid& valueTypeId,
|
||||
AZ::JsonSerializerContext& context) override;
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
bool LoadAny(
|
||||
AZStd::any& propertyValue, const rapidjson::Value& inputPropertyValue, AZ::JsonDeserializerContext& context,
|
||||
AZ::JsonSerializationResult::ResultCode& result);
|
||||
template<typename T>
|
||||
bool StoreAny(
|
||||
const AZStd::any& propertyValue, rapidjson::Value& outputPropertyValue, AZ::JsonSerializerContext& context,
|
||||
AZ::JsonSerializationResult::ResultCode& result);
|
||||
};
|
||||
|
||||
//!!! Start in Graph.h for high level GraphModel documentation !!!
|
||||
|
||||
@@ -180,6 +207,7 @@ namespace GraphModel
|
||||
class Slot : public GraphElement, public AZStd::enable_shared_from_this<Slot>
|
||||
{
|
||||
friend class Graph; // So the Graph can update the Slot's cache of Connection pointers
|
||||
friend class JsonSlotSerializer; // So we can set the m_value and m_subId directly from the serializer
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Slot, AZ::SystemAllocator, 0);
|
||||
|
||||
@@ -1338,11 +1338,7 @@ namespace GraphModelIntegration
|
||||
|
||||
GraphCanvasMetadata* GraphController::GetGraphMetadata()
|
||||
{
|
||||
if (!m_graph->GetUiMetadata().is<GraphCanvasMetadata>())
|
||||
{
|
||||
m_graph->SetUiMetadata(AZStd::any(GraphCanvasMetadata()));
|
||||
}
|
||||
GraphCanvasMetadata* graphCanvasMetadata = AZStd::any_cast<GraphCanvasMetadata>(&m_graph->GetUiMetadata());
|
||||
GraphCanvasMetadata* graphCanvasMetadata = &m_graph->GetUiMetadata();
|
||||
AZ_Assert(graphCanvasMetadata, "GraphCanvasMetadata not initialized");
|
||||
return graphCanvasMetadata;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace GraphModel
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<Graph>()
|
||||
->Version(1)
|
||||
->Version(2)
|
||||
->Field("m_nodes", &Graph::m_nodes)
|
||||
->Field("m_connections", &Graph::m_connections)
|
||||
->Field("m_uiMetadata", &Graph::m_uiMetadata)
|
||||
@@ -312,19 +312,19 @@ namespace GraphModel
|
||||
}
|
||||
|
||||
|
||||
void Graph::SetUiMetadata(const AZStd::any& uiMetadata)
|
||||
void Graph::SetUiMetadata(const GraphModelIntegration::GraphCanvasMetadata& uiMetadata)
|
||||
{
|
||||
m_uiMetadata = uiMetadata;
|
||||
}
|
||||
|
||||
|
||||
const AZStd::any& Graph::GetUiMetadata() const
|
||||
const GraphModelIntegration::GraphCanvasMetadata& Graph::GetUiMetadata() const
|
||||
{
|
||||
return m_uiMetadata;
|
||||
}
|
||||
|
||||
|
||||
AZStd::any& Graph::GetUiMetadata()
|
||||
GraphModelIntegration::GraphCanvasMetadata& Graph::GetUiMetadata()
|
||||
{
|
||||
return m_uiMetadata;
|
||||
}
|
||||
|
||||
@@ -11,9 +11,14 @@
|
||||
*/
|
||||
|
||||
// AZ
|
||||
#include <AzCore/Math/Color.h>
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Vector4.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/Json/RegistrationContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
// Graph Model
|
||||
@@ -294,13 +299,164 @@ namespace GraphModel
|
||||
/////////////////////////////////////////////////////////
|
||||
// Slot
|
||||
|
||||
AZ::JsonSerializationResult::Result JsonSlotSerializer::Load(
|
||||
void* outputValue, const AZ::Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
|
||||
AZ::JsonDeserializerContext& context)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
AZ_Assert(
|
||||
azrtti_typeid<Slot>() == outputValueTypeId,
|
||||
"Unable to deserialize Slot from json because the provided type is %s.",
|
||||
outputValueTypeId.ToString<AZStd::string>().c_str());
|
||||
|
||||
Slot* slot = reinterpret_cast<Slot*>(outputValue);
|
||||
AZ_Assert(slot, "Output value for JsonSlotSerializer can't be null.");
|
||||
|
||||
JSR::ResultCode result(JSR::Tasks::ReadField);
|
||||
|
||||
auto serializedSlotValue = inputValue.FindMember("m_value");
|
||||
if (serializedSlotValue != inputValue.MemberEnd())
|
||||
{
|
||||
AZStd::any slotValue;
|
||||
if (LoadAny<bool>(slotValue, serializedSlotValue->value, context, result) ||
|
||||
LoadAny<int>(slotValue, serializedSlotValue->value, context, result) ||
|
||||
LoadAny<float>(slotValue, serializedSlotValue->value, context, result) ||
|
||||
LoadAny<AZStd::string>(slotValue, serializedSlotValue->value, context, result) ||
|
||||
LoadAny<AZ::Vector2>(slotValue, serializedSlotValue->value, context, result) ||
|
||||
LoadAny<AZ::Vector3>(slotValue, serializedSlotValue->value, context, result) ||
|
||||
LoadAny<AZ::Vector4>(slotValue, serializedSlotValue->value, context, result) ||
|
||||
LoadAny<AZ::EntityId>(slotValue, serializedSlotValue->value, context, result))
|
||||
{
|
||||
slot->m_value = slotValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Load m_subId normally because it's just an int
|
||||
{
|
||||
SlotSubId slotSubId = 0;
|
||||
result.Combine(ContinueLoadingFromJsonObjectField(
|
||||
&slotSubId, azrtti_typeid<SlotSubId>(), inputValue,
|
||||
"m_subId", context));
|
||||
slot->m_subId = slotSubId;
|
||||
}
|
||||
|
||||
return context.Report(
|
||||
result,
|
||||
result.GetProcessing() != JSR::Processing::Halted ? "Succesfully loaded Slot information."
|
||||
: "Failed to load Slot information.");
|
||||
}
|
||||
|
||||
AZ::JsonSerializationResult::Result JsonSlotSerializer::Store(
|
||||
rapidjson::Value& outputValue, const void* inputValue, [[maybe_unused]] const void* defaultValue, const AZ::Uuid& valueTypeId,
|
||||
AZ::JsonSerializerContext& context)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
AZ_Assert(
|
||||
azrtti_typeid<Slot>() == valueTypeId,
|
||||
"Unable to Serialize Slot because the provided type is %s.", valueTypeId.ToString<AZStd::string>().c_str());
|
||||
|
||||
const Slot* slot = reinterpret_cast<const Slot*>(inputValue);
|
||||
AZ_Assert(slot, "Input value for JsonSlotSerializer can't be null.");
|
||||
|
||||
outputValue.SetObject();
|
||||
|
||||
JSR::ResultCode result(JSR::Tasks::WriteValue);
|
||||
|
||||
{
|
||||
AZ::ScopedContextPath subPathPropertyOverrides(context, "m_value");
|
||||
|
||||
if (!slot->m_value.empty())
|
||||
{
|
||||
rapidjson::Value outputPropertyValue;
|
||||
if (StoreAny<bool>(slot->m_value, outputPropertyValue, context, result) ||
|
||||
StoreAny<int>(slot->m_value, outputPropertyValue, context, result) ||
|
||||
StoreAny<float>(slot->m_value, outputPropertyValue, context, result) ||
|
||||
StoreAny<AZStd::string>(slot->m_value, outputPropertyValue, context, result) ||
|
||||
StoreAny<AZ::Vector2>(slot->m_value, outputPropertyValue, context, result) ||
|
||||
StoreAny<AZ::Vector3>(slot->m_value, outputPropertyValue, context, result) ||
|
||||
StoreAny<AZ::Vector4>(slot->m_value, outputPropertyValue, context, result) ||
|
||||
StoreAny<AZ::EntityId>(slot->m_value, outputPropertyValue, context, result))
|
||||
{
|
||||
outputValue.AddMember("m_value", outputPropertyValue, context.GetJsonAllocator());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
AZ::ScopedContextPath subSlotId(context, "m_subId");
|
||||
SlotSubId defaultSubId = 0;
|
||||
|
||||
result.Combine(ContinueStoringToJsonObjectField(
|
||||
outputValue, "m_subId", &slot->m_subId, &defaultSubId,
|
||||
azrtti_typeid<SlotSubId>(), context));
|
||||
}
|
||||
|
||||
return context.Report(
|
||||
result,
|
||||
result.GetProcessing() != JSR::Processing::Halted ? "Successfully stored MaterialAssignment information."
|
||||
: "Failed to store MaterialAssignment information.");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool JsonSlotSerializer::LoadAny(
|
||||
AZStd::any& propertyValue, const rapidjson::Value& inputPropertyValue, AZ::JsonDeserializerContext& context,
|
||||
AZ::JsonSerializationResult::ResultCode& result)
|
||||
{
|
||||
auto valueItr = inputPropertyValue.FindMember("Value");
|
||||
auto typeItr = inputPropertyValue.FindMember("$type");
|
||||
if ((valueItr != inputPropertyValue.MemberEnd()) && (typeItr != inputPropertyValue.MemberEnd()))
|
||||
{
|
||||
// Requiring explicit type info to differentiate between colors versus vectors and numeric types
|
||||
const AZ::Uuid baseTypeId = azrtti_typeid<T>();
|
||||
AZ::Uuid typeId = AZ::Uuid::CreateNull();
|
||||
result.Combine(LoadTypeId(typeId, inputPropertyValue, context, &baseTypeId));
|
||||
|
||||
if (typeId == azrtti_typeid<T>())
|
||||
{
|
||||
T value;
|
||||
result.Combine(ContinueLoadingFromJsonObjectField(&value, azrtti_typeid<T>(), inputPropertyValue, "Value", context));
|
||||
propertyValue = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool JsonSlotSerializer::StoreAny(
|
||||
const AZStd::any& propertyValue, rapidjson::Value& outputPropertyValue, AZ::JsonSerializerContext& context,
|
||||
AZ::JsonSerializationResult::ResultCode& result)
|
||||
{
|
||||
if (propertyValue.is<T>())
|
||||
{
|
||||
outputPropertyValue.SetObject();
|
||||
|
||||
// Storing explicit type info to differentiate between colors versus vectors and numeric types
|
||||
rapidjson::Value typeValue;
|
||||
result.Combine(StoreTypeId(typeValue, azrtti_typeid<T>(), context));
|
||||
outputPropertyValue.AddMember("$type", typeValue, context.GetJsonAllocator());
|
||||
|
||||
T value = AZStd::any_cast<T>(propertyValue);
|
||||
result.Combine(
|
||||
ContinueStoringToJsonObjectField(outputPropertyValue, "Value", &value, nullptr, azrtti_typeid<T>(), context));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Slot::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
if (auto jsonContext = azrtti_cast<AZ::JsonRegistrationContext*>(context))
|
||||
{
|
||||
jsonContext->Serializer<JsonSlotSerializer>()->HandlesType<Slot>();
|
||||
}
|
||||
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<Slot>()
|
||||
->Version(0)
|
||||
->Version(1)
|
||||
->Field("m_value", &Slot::m_value)
|
||||
->Field("m_subId", &Slot::m_subId)
|
||||
// m_slotDescription is not reflected because that data is populated procedurally by each node
|
||||
|
||||
@@ -460,10 +460,10 @@ namespace LandscapeCanvasEditor
|
||||
GraphCanvas::StyleManagerRequestBus::Event(editorId, &GraphCanvas::StyleManagerRequests::RegisterDataPaletteStyle, LandscapeCanvas::AreaTypeId, "VegetationAreaDataColorPalette");
|
||||
|
||||
LandscapeCanvas::LandscapeCanvasRequestBus::Handler::BusConnect();
|
||||
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
|
||||
AzToolsFramework::EditorPickModeNotificationBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId());
|
||||
AzToolsFramework::EntityCompositionNotificationBus::Handler::BusConnect();
|
||||
AzToolsFramework::ToolsApplicationNotificationBus::Handler::BusConnect();
|
||||
AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusConnect();
|
||||
CrySystemEventBus::Handler::BusConnect();
|
||||
AZ::EntitySystemBus::Handler::BusConnect();
|
||||
|
||||
@@ -480,6 +480,7 @@ namespace LandscapeCanvasEditor
|
||||
{
|
||||
AZ::EntitySystemBus::Handler::BusDisconnect();
|
||||
CrySystemEventBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::ToolsApplicationNotificationBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorPickModeNotificationBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
|
||||
@@ -883,6 +884,10 @@ namespace LandscapeCanvasEditor
|
||||
if (landscapeCanvasComponent)
|
||||
{
|
||||
landscapeCanvasComponent->m_graph = *m_serializeContext->CloneObject(graph.get());
|
||||
|
||||
// Mark the Landscape Canvas entity as dirty so the changes to the graph will be picked up on the next save
|
||||
AzToolsFramework::ScopedUndoBatch undo("Update Landscape Canvas Graph");
|
||||
AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast(&AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, rootEntityId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1572,7 +1577,7 @@ namespace LandscapeCanvasEditor
|
||||
|
||||
void MainWindow::HandleEditorEntityCreated(const AZ::EntityId& entityId, GraphCanvas::GraphId graphId)
|
||||
{
|
||||
if (m_ignoreGraphUpdates)
|
||||
if (m_ignoreGraphUpdates || m_prefabPropagationInProgress)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1622,6 +1627,11 @@ namespace LandscapeCanvasEditor
|
||||
|
||||
void MainWindow::OnEditorEntityDeleted(const AZ::EntityId& entityId)
|
||||
{
|
||||
if (m_prefabPropagationInProgress)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_queuedEntityDeletes.push_back(entityId);
|
||||
|
||||
QTimer::singleShot(0, [this, entityId]() {
|
||||
@@ -2456,6 +2466,11 @@ namespace LandscapeCanvasEditor
|
||||
|
||||
void MainWindow::EntityParentChanged(AZ::EntityId entityId, AZ::EntityId newParentId, AZ::EntityId oldParentId)
|
||||
{
|
||||
if (m_prefabPropagationInProgress)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GraphCanvas::GraphId oldGraphId = FindGraphContainingEntity(oldParentId);
|
||||
GraphCanvas::GraphId newGraphId = FindGraphContainingEntity(newParentId);
|
||||
|
||||
@@ -2482,6 +2497,20 @@ namespace LandscapeCanvasEditor
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::OnPrefabInstancePropagationBegin()
|
||||
{
|
||||
// Ignore graph updates during prefab propagation because the entities will be
|
||||
// deleted and re-created, which would inadvertantly trigger our logic to close
|
||||
// the graph when the corresponding entity is deleted.
|
||||
m_prefabPropagationInProgress = true;
|
||||
}
|
||||
|
||||
void MainWindow::OnPrefabInstancePropagationEnd()
|
||||
{
|
||||
// See comment above in OnPrefabInstancePropagationBegin
|
||||
m_prefabPropagationInProgress = false;
|
||||
}
|
||||
|
||||
void MainWindow::OnCryEditorEndCreate()
|
||||
{
|
||||
UpdateGraphEnabled();
|
||||
@@ -2490,6 +2519,15 @@ namespace LandscapeCanvasEditor
|
||||
void MainWindow::OnCryEditorEndLoad()
|
||||
{
|
||||
UpdateGraphEnabled();
|
||||
|
||||
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void MainWindow::OnCryEditorCloseScene()
|
||||
{
|
||||
UpdateGraphEnabled();
|
||||
|
||||
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void MainWindow::OnCryEditorSceneClosed()
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <AzToolsFramework/API/EntityCompositionNotificationBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicNotificationBus.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
|
||||
@@ -84,6 +85,7 @@ namespace LandscapeCanvasEditor
|
||||
, private AzToolsFramework::EntityCompositionNotificationBus::Handler
|
||||
, private AzToolsFramework::PropertyEditorEntityChangeNotificationBus::MultiHandler
|
||||
, private AzToolsFramework::ToolsApplicationNotificationBus::Handler
|
||||
, private AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
|
||||
, private CrySystemEventBus::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -183,10 +185,15 @@ namespace LandscapeCanvasEditor
|
||||
void EntityParentChanged(AZ::EntityId entityId, AZ::EntityId newParentId, AZ::EntityId oldParentId) override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! PrefabPublicNotificationBus overrides
|
||||
void OnPrefabInstancePropagationBegin() override;
|
||||
void OnPrefabInstancePropagationEnd() override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// CrySystemEventBus overrides
|
||||
void OnCryEditorEndCreate() override;
|
||||
void OnCryEditorEndLoad() override;
|
||||
void OnCryEditorCloseScene() override;
|
||||
void OnCryEditorSceneClosed() override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -246,6 +253,7 @@ namespace LandscapeCanvasEditor
|
||||
AZ::SerializeContext* m_serializeContext = nullptr;
|
||||
|
||||
bool m_ignoreGraphUpdates = false;
|
||||
bool m_prefabPropagationInProgress = false;
|
||||
bool m_inObjectPickMode = false;
|
||||
|
||||
using DeletedNodePositionsMap = AZStd::unordered_map<AZ::EntityComponentIdPair, AZ::Vector2>;
|
||||
|
||||
Reference in New Issue
Block a user