This commit is contained in:
luissemp
2021-04-16 09:32:17 -07:00
96 changed files with 1171 additions and 343 deletions
@@ -12,4 +12,5 @@
set(GEM_DEPENDENCIES
Gem::Atom_RHI_Vulkan.Private
Gem::Atom_RHI_DX12.Private
Gem::Atom_RHI_Null.Private
)
@@ -15,5 +15,7 @@ set(GEM_DEPENDENCIES
Gem::Atom_RHI_Vulkan.Builders
Gem::Atom_RHI_DX12.Private
Gem::Atom_RHI_DX12.Builders
Gem::Atom_RHI_Null.Private
Gem::Atom_RHI_Null.Builders
Gem::Atom_RHI_Metal.Builders
)
@@ -138,6 +138,7 @@ endif()
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_pytest(
NAME AutomatedTesting::BlastTests
TEST_SUITE sandbox
TEST_SERIAL TRUE
PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py
TIMEOUT 3600
@@ -26,7 +26,7 @@ namespace AZ
{
class Transform;
using TransformChangedEvent = Event<Transform, Transform>;
using TransformChangedEvent = Event<const Transform&, const Transform&>;
using ParentChangedEvent = Event<EntityId, EntityId>;
@@ -142,6 +142,7 @@ namespace Physics
->Field("PhysicsAsset", &PhysicsAssetShapeConfiguration::m_asset)
->Field("AssetScale", &PhysicsAssetShapeConfiguration::m_assetScale)
->Field("UseMaterialsFromAsset", &PhysicsAssetShapeConfiguration::m_useMaterialsFromAsset)
->Field("SubdivisionLevel", &PhysicsAssetShapeConfiguration::m_subdivisionLevel)
;
if (auto editContext = serializeContext->GetEditContext())
@@ -141,6 +141,7 @@ namespace Physics
AZ::Data::Asset<AZ::Data::AssetData> m_asset{ AZ::Data::AssetLoadBehavior::PreLoad };
AZ::Vector3 m_assetScale = AZ::Vector3::CreateOne();
bool m_useMaterialsFromAsset = true;
AZ::u8 m_subdivisionLevel = 4; ///< The level of subdivision if a primitive shape is replaced with a convex mesh due to scaling.
};
class NativeShapeConfiguration : public ShapeConfiguration
@@ -142,13 +142,6 @@ namespace Physics
virtual AZStd::shared_ptr<Shape> CreateShape(const ColliderConfiguration& colliderConfiguration, const ShapeConfiguration& configuration) = 0;
/// Adds an appropriate collider component to the entity based on the provided shape configuration.
/// @param entity Entity where the component should be added to.
/// @param colliderConfiguration Configuration of the collider.
/// @param shapeConfiguration Configuration of the shape of the collider.
/// @param addEditorComponents Tells whether to add the Editor version of the collider component or the Game one.
virtual void AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, bool addEditorComponents = false) = 0;
/// Releases the mesh object created by the physics backend.
/// @param nativeMeshObject Pointer to the mesh object.
virtual void ReleaseNativeMeshObject(void* nativeMeshObject) = 0;
@@ -114,6 +114,9 @@ namespace AzNetworking
void ClearUnusedBits();
ContainerType m_container;
template <AZStd::size_t, typename>
friend class FixedSizeVectorBitset;
};
}
@@ -192,19 +192,11 @@ namespace AzNetworking
template <AZStd::size_t CAPACITY, typename ElementType>
inline void FixedSizeVectorBitset<CAPACITY, ElementType>::ClearUnusedBits()
{
constexpr ElementType AllOnes = static_cast<ElementType>(~0);
const ElementType LastUsedBits = (GetSize() % BitsetType::ElementTypeBits);
#pragma warning(push)
#pragma warning(disable : 4293) // shift count negative or too big, undefined behaviour
#pragma warning(disable : 6326) // constant constant comparison
const ElementType ShiftAmount = (LastUsedBits == 0) ? 0 : BitsetType::ElementTypeBits - LastUsedBits;
const ElementType ClearBitMask = AllOnes >> ShiftAmount;
#pragma warning(pop)
uint32_t usedElementSize = (GetSize() + BitsetType::ElementTypeBits - 1) / BitsetType::ElementTypeBits;
for (uint32_t i = usedElementSize + 1; i < CAPACITY; ++i)
for (uint32_t i = usedElementSize + 1; i < BitsetType::ElementCount; ++i)
{
m_bitset.GetContainer()[i] = 0;
}
m_bitset.GetContainer()[m_bitset.GetContainer().size() - 1] &= ClearBitMask;
m_bitset.ClearUnusedBits();
}
}
@@ -270,7 +270,7 @@ namespace AzNetworking
value.StoreToFloat3(values);
serializer.Serialize(values[0], "xValue");
serializer.Serialize(values[1], "yValue");
serializer.Serialize(values[1], "zValue");
serializer.Serialize(values[2], "zValue");
value = AZ::Vector3::CreateFromFloat3(values);
return serializer.IsValid();
}
@@ -285,8 +285,8 @@ namespace AzNetworking
value.StoreToFloat4(values);
serializer.Serialize(values[0], "xValue");
serializer.Serialize(values[1], "yValue");
serializer.Serialize(values[1], "zValue");
serializer.Serialize(values[1], "wValue");
serializer.Serialize(values[2], "zValue");
serializer.Serialize(values[3], "wValue");
value = AZ::Vector4::CreateFromFloat4(values);
return serializer.IsValid();
}
@@ -301,8 +301,8 @@ namespace AzNetworking
value.StoreToFloat4(values);
serializer.Serialize(values[0], "xValue");
serializer.Serialize(values[1], "yValue");
serializer.Serialize(values[1], "zValue");
serializer.Serialize(values[1], "wValue");
serializer.Serialize(values[2], "zValue");
serializer.Serialize(values[3], "wValue");
value = AZ::Quaternion::CreateFromFloat4(values);
return serializer.IsValid();
}
@@ -45,7 +45,7 @@ namespace AZ
AssetBuilderSDK::AssetBuilderDesc builderDescriptor;
builderDescriptor.m_name = "Atom Resource Pool Asset Builder";
builderDescriptor.m_version = 1;
builderDescriptor.m_version = 2; //ATOM-15196
builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt,
AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
builderDescriptor.m_busId = azrtti_typeid<ResourcePoolBuilder>();
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9d3c18d76f00688d15c54736ef3d8c953df08baf46a796fa71627de18bdb3c0f
size 22804332
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6cbfc4d0a6722726070468da4368df7c76be67e8d067a7e3130fd29cdcdd5c6b
size 7613840
oid sha256:35a880abc018520d4b30d21a64f7a14fca74d936593320d5afd03ddf25771bf3
size 9176416
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/arch_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,17 @@
],
"textureMap": "Textures/arch_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.885053813457489,
0.801281750202179,
1.0
]
},
"metallic": {
"textureMap": "Textures/arch_1k_metallic.png"
},
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/background_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,23 @@
],
"textureMap": "Textures/background_1k_basecolor.png"
},
"clearCoat": {
"enable": true,
"factor": 0.5,
"normalMap": "Textures/background_1k_normal.jpg",
"roughness": 0.4000000059604645
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.8911573886871338,
0.7894102334976196,
1.0
]
},
"metallic": {
"textureMap": "Textures/background_1k_metallic.png"
},
@@ -24,7 +45,6 @@
},
"parallax": {
"algorithm": "POM",
"enable": true,
"factor": 0.03099999949336052,
"pdo": true,
"quality": "High",
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/bricks_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,23 @@
],
"textureMap": "Textures/bricks_1k_basecolor.png"
},
"clearCoat": {
"enable": true,
"factor": 0.5,
"normalMap": "Textures/bricks_1k_normal.jpg",
"roughness": 0.5
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.9703211784362793,
0.9703211784362793,
1.0
]
},
"metallic": {
"textureMap": "Textures/bricks_1k_metallic.png"
},
@@ -23,11 +44,9 @@
"factor": 1.0
},
"parallax": {
"algorithm": "POM",
"enable": true,
"algorithm": "ContactRefinement",
"factor": 0.03500000014901161,
"pdo": true,
"quality": "High",
"quality": "Medium",
"textureMap": "Textures/bricks_1k_height.png"
},
"roughness": {
@@ -4,17 +4,55 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/ceiling_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
0.800000011920929,
0.800000011920929,
1.0
],
"textureBlendMode": "Lerp",
"textureMap": "Textures/ceiling_1k_basecolor.png"
},
"clearCoat": {
"enable": true,
"factor": 0.5,
"influenceMap": "Textures/ceiling_1k_ao.png",
"normalMap": "Textures/ceiling_1k_normal.png",
"roughness": 0.30000001192092898
},
"emissive": {
"color": [
0.0,
0.0,
0.0,
1.0
]
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.7591058015823364,
0.43776607513427737,
1.0
]
},
"normal": {
"textureMap": "Textures/ceiling_1k_normal.png"
},
"opacity": {
"factor": 1.0
},
"parallax": {
"algorithm": "ContactRefinement",
"factor": 0.019999999552965165,
"pdo": true,
"quality": "Medium",
"textureMap": "Textures/ceiling_1k_height.png"
},
"roughness": {
"textureMap": "Textures/ceiling_1k_roughness.png"
}
}
}
@@ -13,6 +13,17 @@
],
"textureMap": "Textures/chain_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
0.4891279339790344,
0.7931944727897644,
1.0,
1.0
]
},
"metallic": {
"textureMap": "Textures/chain_alpha.png"
},
@@ -21,7 +32,7 @@
},
"opacity": {
"alphaSource": "Split",
"factor": 1.0,
"factor": 0.30000001192092898,
"mode": "Cutout",
"textureMap": "Textures/chain_alpha.png"
},
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/columnA_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,23 @@
],
"textureMap": "Textures/columnA_1k_basecolor.png"
},
"clearCoat": {
"enable": true,
"factor": 0.5,
"normalMap": "Textures/columnA_1k_normal.jpg",
"roughness": 0.30000001192092898
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.8964369893074036,
0.8264744281768799,
1.0
]
},
"metallic": {
"textureMap": "Textures/columnA_1k_metallic.png"
},
@@ -24,7 +45,6 @@
},
"parallax": {
"algorithm": "POM",
"enable": true,
"factor": 0.017000000923871995,
"pdo": true,
"quality": "High",
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/columnB_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,23 @@
],
"textureMap": "Textures/columnB_1k_basecolor.png"
},
"clearCoat": {
"enable": true,
"factor": 0.5,
"normalMap": "Textures/columnB_1k_normal.jpg",
"roughness": 0.30000001192092898
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.9015335440635681,
0.8348516225814819,
1.0
]
},
"metallic": {
"textureMap": "Textures/columnB_1k_metallic.png"
},
@@ -23,7 +44,6 @@
"factor": 1.0
},
"parallax": {
"enable": true,
"factor": 0.020999999716877939,
"pdo": true,
"quality": "High",
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/columnC_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,23 @@
],
"textureMap": "Textures/columnC_1k_basecolor.png"
},
"clearCoat": {
"enable": true,
"factor": 0.5,
"normalMap": "Textures/columnC_1k_normal.jpg",
"roughness": 0.30000001192092898
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
0.9050736427307129,
0.9050736427307129,
1.0,
1.0
]
},
"metallic": {
"textureMap": "Textures/columnC_1k_metallic.png"
},
@@ -24,7 +45,6 @@
},
"parallax": {
"algorithm": "POM",
"enable": true,
"factor": 0.014000000432133675,
"pdo": true,
"quality": "High",
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/curtain_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,10 +17,22 @@
],
"textureMap": "Textures/curtainBlue_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
0.06195162981748581,
0.2056153267621994,
1.0,
1.0
]
},
"metallic": {
"textureMap": "Textures/curtain_metallic.png"
},
"normal": {
"factor": 0.5,
"textureMap": "Textures/curtain_normal.jpg"
},
"opacity": {
@@ -24,6 +40,9 @@
},
"roughness": {
"textureMap": "Textures/curtain_roughness.png"
},
"specularF0": {
"enableMultiScatterCompensation": true
}
}
}
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/curtain_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,10 +17,22 @@
],
"textureMap": "Textures/curtainGreen_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
0.0,
1.0,
0.029526207596063615,
1.0
]
},
"metallic": {
"textureMap": "Textures/curtain_metallic.png"
},
"normal": {
"factor": 0.5,
"textureMap": "Textures/curtain_normal.jpg"
},
"opacity": {
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/curtain_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,17 @@
],
"textureMap": "Textures/curtainRed_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.023315785452723504,
0.048538949340581897,
1.0
]
},
"metallic": {
"textureMap": "Textures/curtain_metallic.png"
},
@@ -24,6 +39,12 @@
},
"roughness": {
"textureMap": "Textures/curtain_roughness.png"
},
"uv": {
"center": [
16.0,
0.0
]
}
}
}
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/details_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,15 @@
],
"textureMap": "Textures/details_1k_basecolor.png"
},
"clearCoat": {
"enable": true,
"factor": 0.5,
"normalMap": "Textures/details_1k_normal.png",
"roughness": 0.25
},
"general": {
"applySpecularAA": true
},
"metallic": {
"textureMap": "Textures/details_1k_metallic.png"
},
@@ -24,7 +37,6 @@
},
"parallax": {
"algorithm": "POM",
"enable": true,
"factor": 0.02500000037252903,
"pdo": true,
"textureMap": "Textures/details_1k_height.png"
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/fabric_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,10 +17,22 @@
],
"textureMap": "Textures/fabricBlue_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
0.0,
0.15049973130226136,
1.0,
1.0
]
},
"metallic": {
"textureMap": "Textures/fabric_metallic.png"
},
"normal": {
"factor": 0.5,
"textureMap": "Textures/fabric_normal.jpg"
},
"opacity": {
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/fabric_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,10 +17,22 @@
],
"textureMap": "Textures/fabricGreen_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
0.0,
1.0,
0.15378041565418244,
1.0
]
},
"metallic": {
"textureMap": "Textures/fabric_metallic.png"
},
"normal": {
"factor": 0.5,
"textureMap": "Textures/fabric_normal.jpg"
},
"opacity": {
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/fabric_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,10 +17,22 @@
],
"textureMap": "Textures/fabricRed_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.08197146654129029,
0.10267795622348786,
1.0
]
},
"metallic": {
"textureMap": "Textures/fabric_metallic.png"
},
"normal": {
"factor": 0.5,
"textureMap": "Textures/fabric_normal.jpg"
},
"opacity": {
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/flagpole_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,17 @@
],
"textureMap": "Textures/flagpole_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.6520485281944275,
0.7122911214828491,
1.0
]
},
"metallic": {
"textureMap": "Textures/flagpole_1k_metallic.png"
},
@@ -24,7 +39,6 @@
},
"parallax": {
"algorithm": "POM",
"enable": true,
"factor": 0.014000000432133675,
"pdo": true,
"quality": "High",
@@ -32,6 +46,9 @@
},
"roughness": {
"textureMap": "Textures/flagpole_1k_roughness.png"
},
"specularF0": {
"enableMultiScatterCompensation": true
}
}
}
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/floor_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,23 @@
],
"textureMap": "Textures/floor_1k_basecolor.png"
},
"clearCoat": {
"enable": true,
"influenceMap": "Textures/floor_1k_ao.png",
"normalMap": "Textures/floor_1k_normal.png",
"roughness": 0.25
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.9404135346412659,
0.8688944578170776,
1.0
]
},
"normal": {
"textureMap": "Textures/floor_1k_normal.png"
},
@@ -21,7 +42,6 @@
},
"parallax": {
"algorithm": "POM",
"enable": true,
"factor": 0.012000000104308129,
"pdo": true,
"textureMap": "Textures/floor_1k_height.png"
@@ -13,6 +13,23 @@
],
"textureMap": "Textures/thorn_basecolor.png"
},
"clearCoat": {
"enable": true,
"factor": 0.05000000074505806,
"normalMap": "Textures/thorn_normal.jpg",
"roughness": 0.10000000149011612
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
0.46506446599960329,
1.0,
0.3944609761238098,
1.0
]
},
"metallic": {
"textureMap": "Textures/thorn_metallic.png"
},
@@ -20,7 +37,8 @@
"textureMap": "Textures/thorn_normal.jpg"
},
"opacity": {
"factor": 0.5699999928474426,
"doubleSided": true,
"factor": 0.20000000298023225,
"mode": "Cutout"
},
"parallax": {
@@ -28,6 +46,25 @@
},
"roughness": {
"textureMap": "Textures/thorn_roughness.png"
},
"subsurfaceScattering": {
"enableSubsurfaceScattering": true,
"quality": 1.0,
"scatterColor": [
0.28143739700317385,
1.0,
0.13000686466693879,
1.0
],
"scatterDistance": 1.0,
"thickness": 0.10000000149011612,
"transmissionMode": "ThinObject",
"transmissionTint": [
0.07225146889686585,
0.16981765627861024,
0.04444953054189682,
1.0
]
}
}
}
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/lion_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,17 @@
],
"textureMap": "Textures/lion_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.7364919781684876,
0.3672388792037964,
1.0
]
},
"metallic": {
"textureMap": "Textures/lion_1k_metallic.png"
},
@@ -23,14 +38,18 @@
"factor": 1.0
},
"parallax": {
"algorithm": "POM",
"algorithm": "ContactRefinement",
"enable": true,
"factor": 0.023000000044703485,
"factor": 0.009999999776482582,
"pdo": true,
"quality": "Ultra",
"textureMap": "Textures/lion_1k_height.png"
},
"roughness": {
"textureMap": "Textures/lion_1k_roughness.png"
},
"specularF0": {
"enableMultiScatterCompensation": true
}
}
}
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/roof_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -11,24 +15,27 @@
0.800000011920929,
1.0
],
"textureBlendMode": "Lerp",
"textureMap": "Textures/roof_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"metallic": {
"factor": 0.009999999776482582,
"useTexture": false
},
"normal": {
"factor": 0.5,
"flipY": true,
"textureMap": "Textures/roof_1k_normal.jpg"
},
"opacity": {
"factor": 1.0
},
"parallax": {
"algorithm": "POM",
"enable": true,
"algorithm": "ContactRefinement",
"factor": 0.019999999552965165,
"pdo": true,
"quality": "High",
"quality": "Medium",
"textureMap": "Textures/roof_1k_height.png"
},
"roughness": {
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/vase_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,17 @@
],
"textureMap": "Textures/vase_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.8713664412498474,
0.6021667718887329,
1.0
]
},
"metallic": {
"textureMap": "Textures/vase_1k_metallic.png"
},
@@ -24,7 +39,6 @@
},
"parallax": {
"algorithm": "POM",
"enable": true,
"factor": 0.027000000700354577,
"pdo": true,
"quality": "High",
@@ -32,6 +46,9 @@
},
"roughness": {
"textureMap": "Textures/vase_1k_roughness.png"
},
"specularF0": {
"enableMultiScatterCompensation": true
}
}
}
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/vaseHanging_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,17 @@
],
"textureMap": "Textures/vaseHanging_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
0.765606164932251,
1.0,
0.7052567601203919,
1.0
]
},
"metallic": {
"textureMap": "Textures/vaseHanging_1k_metallic.png"
},
@@ -24,7 +39,6 @@
},
"parallax": {
"algorithm": "POM",
"enable": true,
"factor": 0.04600000008940697,
"pdo": true,
"quality": "High",
@@ -13,9 +13,39 @@
],
"textureMap": "Textures/vasePlant_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
0.6788738965988159,
1.0,
0.026138704270124437,
1.0
]
},
"opacity": {
"factor": 0.8399999737739563,
"doubleSided": true,
"factor": 0.28999999165534975,
"mode": "Cutout"
},
"subsurfaceScattering": {
"enableSubsurfaceScattering": true,
"quality": 1.0,
"scatterColor": [
0.07421988248825073,
0.10223544389009476,
0.0,
1.0
],
"subsurfaceScatterFactor": 0.0,
"transmissionMode": "ThinObject",
"transmissionTint": [
0.33716335892677309,
0.4620737135410309,
0.0,
1.0
]
}
}
}
@@ -4,6 +4,10 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"enable": true,
"textureMap": "Textures/vaseRound_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -13,6 +17,24 @@
],
"textureMap": "Textures/vaseRound_1k_basecolor.png"
},
"clearCoat": {
"enable": true,
"factor": 0.5,
"influenceMap": "Textures/vaseRound_1k_ao.png",
"normalMap": "Textures/vaseRound_1k_normal.jpg",
"roughness": 0.25
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.5939116477966309,
0.29176774621009829,
1.0
]
},
"normal": {
"textureMap": "Textures/vaseRound_1k_normal.jpg"
},
@@ -21,7 +43,6 @@
},
"parallax": {
"algorithm": "POM",
"enable": true,
"factor": 0.019999999552965165,
"pdo": true,
"quality": "High",
@@ -29,6 +50,9 @@
},
"roughness": {
"textureMap": "Textures/vaseRound_1k_roughness.png"
},
"specularF0": {
"enableMultiScatterCompensation": true
}
}
}
+1 -1
View File
@@ -44,7 +44,7 @@ CD /d %LY_PROJECT_PATH%\%DEV_REL_PATH%
set LY_DEV=%CD%
echo LY_DEV = %LY_DEV%
CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env.bat
CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env_Maya.bat
rem :: Constant Vars (Global)
rem SET LYPY_GDEBUG=0
@@ -34,7 +34,6 @@ namespace AZ
#if !defined(IMGUI_ENABLED)
class DebugConsole {};
#else
#endif // defined(IMGUI_ENABLED)
////////////////////////////////////////////////////////////////////////////////////////////////
//! A debug console used to enter debug console commands and display debug log messages.
//!
@@ -132,4 +131,5 @@ namespace AZ
bool m_autoScroll = true; //!< Should we auto-scroll as new entries are added?
bool m_forceScroll = false; //!< Do we need to force scroll after input entered?
};
#endif // defined(IMGUI_ENABLED)
} // namespace AZ
@@ -158,10 +158,10 @@ def bootstrap_dccsi_py_libs(dccsi_dirpath=return_stub_dir()):
"""Builds and adds local site dir libs based on py version"""
from azpy.constants import STR_DCCSI_PYTHON_LIB_PATH # a path string constructor
_DCCSI_PYTHON_LIB_PATH = "E:\\P4\\jromnoa_spectra_atom_2\\dev\\Tools\\Python\\3.7.5\\windows\\Lib\\site-packages"
# _DCCSI_PYTHON_LIB_PATH = STR_DCCSI_PYTHON_LIB_PATH.format(dccsi_dirpath,
# sys.version_info[0],
# sys.version_info[1])
#_DCCSI_PYTHON_LIB_PATH = "E:\\P4\\jromnoa_spectra_atom_2\\dev\\Tools\\Python\\3.7.5\\windows\\Lib\\site-packages"
_DCCSI_PYTHON_LIB_PATH = STR_DCCSI_PYTHON_LIB_PATH.format(dccsi_dirpath,
sys.version_info[0],
sys.version_info[1])
if os.path.exists(_DCCSI_PYTHON_LIB_PATH):
_LOGGER.debug('Performed site.addsitedir({})'.format(_DCCSI_PYTHON_LIB_PATH))
-3
View File
@@ -213,9 +213,6 @@ namespace Blast
CreateShape,
AZStd::shared_ptr<Physics::Shape>(
const Physics::ColliderConfiguration&, const Physics::ShapeConfiguration&));
MOCK_METHOD4(
AddColliderComponentToEntity,
void(AZ::Entity*, const Physics::ColliderConfiguration&, const Physics::ShapeConfiguration&, bool));
MOCK_METHOD1(ReleaseNativeMeshObject, void(void*));
MOCK_METHOD1(CreateMaterial, AZStd::shared_ptr<Physics::Material>(const Physics::MaterialConfiguration&));
MOCK_METHOD0(GetDefaultMaterial, AZStd::shared_ptr<Physics::Material>());
@@ -33,7 +33,6 @@ namespace Physics
BusDisconnect();
}
MOCK_METHOD2(CreateShape, AZStd::shared_ptr<Physics::Shape>(const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& configuration));
MOCK_METHOD4(AddColliderComponentToEntity, void(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, bool addEditorComponents));
MOCK_METHOD1(ReleaseNativeMeshObject, void(void* nativeMeshObject));
MOCK_METHOD1(CreateMaterial, AZStd::shared_ptr<Physics::Material>(const Physics::MaterialConfiguration& materialConfiguration));
MOCK_METHOD0(GetDefaultMaterial, AZStd::shared_ptr<Physics::Material>());
@@ -217,6 +217,7 @@ namespace LmbrCentral
AZ::TransformBus::EventResult(m_currentTransform, entityId, &AZ::TransformBus::Events::GetWorldTM);
m_currentNonUniformScale = AZ::Vector3::CreateOne();
AZ::NonUniformScaleRequestBus::EventResult(m_currentNonUniformScale, m_entityId, &AZ::NonUniformScaleRequests::GetScale);
m_polygonPrism->SetNonUniformScale(m_currentNonUniformScale);
m_intersectionDataCache.InvalidateCache(InvalidateShapeCacheReason::ShapeChange);
AZ::TransformNotificationBus::Handler::BusConnect(entityId);
@@ -95,4 +95,20 @@ namespace Multiplayer
private:
MultiplayerStats m_stats;
};
inline const char* GetEnumString(MultiplayerAgentType value)
{
switch (value)
{
case MultiplayerAgentType::Uninitialized:
return "Uninitialized";
case MultiplayerAgentType::Client:
return "Client";
case MultiplayerAgentType::ClientServer:
return "ClientServer";
case MultiplayerAgentType::DedicatedServer:
return "DedicatedServer";
}
return "INVALID";
}
}
@@ -1,6 +1,7 @@
#pragma once
#include <AzCore/std/containers/list.h>
#include <Source/MultiplayerTypes.h>
namespace AZ
{
@@ -17,7 +18,13 @@ namespace {{ Namespace }}
{% set ComponentName = Component.attrib['Name'] %}
{{ ComponentName }},
{% endfor %}
Count
};
static_assert(ComponentTypes::Count < static_cast<ComponentTypes>(Multiplayer::InvalidNetComponentId), "ComponentId overflow");
//! For reflecting multiplayer components into the serialize, edit, and behaviour contexts.
void CreateComponentDescriptors(AZStd::list<AZ::ComponentDescriptor*>& descriptors);
//! For creating multiplayer component network inputs.
void CreateComponentNetworkInput();
}
@@ -33,22 +33,20 @@ const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}() const;
#}
{% macro DeclareNetworkPropertySetter(Property) %}
{% set PropertyName = UpperFirst(Property.attrib['Name']) %}
{% if Property.attrib['IsPredictable'] | booleanTrue %}
{% if Property.attrib['Container'] == 'Array' %}
void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index, const {{ Property.attrib['Type'] }}& value);
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index);
{% elif Property.attrib['Container'] == 'Vector' %}
void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index, const {{ Property.attrib['Type'] }}& value);
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index);
bool {{ PropertyName }}PushBack(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value);
bool {{ PropertyName }}PopBack(const Multiplayer::NetworkInput&);
void {{ PropertyName }}Clear(const Multiplayer::NetworkInput&);
{% elif Property.attrib['Container'] == 'Object' %}
void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value);
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&);
{% else %}
void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value);
{% endif %}
{% if Property.attrib['Container'] == 'Array' %}
void Set{{ PropertyName }}(int32_t index, const {{ Property.attrib['Type'] }}& value);
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(int32_t index);
{% elif Property.attrib['Container'] == 'Vector' %}
void Set{{ PropertyName }}(int32_t index, const {{ Property.attrib['Type'] }}& value);
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(int32_t index);
bool {{ PropertyName }}PushBack(const {{ Property.attrib['Type'] }}& value);
bool {{ PropertyName }}PopBack();
void {{ PropertyName }}Clear();
{% elif Property.attrib['Container'] == 'Object' %}
void Set{{ PropertyName }}(const {{ Property.attrib['Type'] }}& value);
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}();
{% else %}
void Set{{ PropertyName }}(const {{ Property.attrib['Type'] }}& value);
{% endif %}
{% endmacro %}
{#
@@ -417,6 +415,7 @@ namespace {{ Component.attrib['Namespace'] }}
static const Multiplayer::NetComponentId s_componentId = static_cast<Multiplayer::NetComponentId>({{ Component.attrib['Namespace'] }}::ComponentTypes::{{ Component.attrib['Name'] }});
static void Reflect(AZ::ReflectContext* context);
static void ReflectToEditContext(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
@@ -73,18 +73,17 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}AddEvent(AZ::Even
{#
#}
{% macro DefineNetworkPropertyPredictableSet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) %}
{% if Property.attrib['IsPredictable'] | booleanTrue %}
{% if Property.attrib['Container'] == 'Array' %}
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput& inputCommand, int32_t index, const {{ Property.attrib['Type'] }}& value)
{% macro DefineNetworkPropertySet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) %}
{% if Property.attrib['Container'] == 'Array' %}
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(int32_t index, const {{ Property.attrib['Type'] }}& value)
{
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index] != value)
{
Modify{{ UpperFirst(Property.attrib['Name']) }}(inputCommand, index) = value;
Modify{{ UpperFirst(Property.attrib['Name']) }}(index) = value;
}
}
{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&, int32_t index)
{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(int32_t index)
{
int32_t bitIndex = index + static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }});
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true);
@@ -92,16 +91,16 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multipl
return GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index];
}
{% elif Property.attrib['Container'] == 'Vector' %}
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput& inputCommand, int32_t index, const {{ Property.attrib['Type'] }}& value)
{% elif Property.attrib['Container'] == 'Vector' %}
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(int32_t index, const {{ Property.attrib['Type'] }}& value)
{
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index] != value)
{
Modify{{ UpperFirst(Property.attrib['Name']) }}(inputCommand, index) = value;
Modify{{ UpperFirst(Property.attrib['Name']) }}(index) = value;
}
}
{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&, int32_t index)
{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(int32_t index)
{
int32_t bitIndex = index + static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }});
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true);
@@ -109,7 +108,7 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multipl
return GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index];
}
bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const Multiplayer::NetworkInput& inputCommand, const {{ Property.attrib['Type'] }} &value)
bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const {{ Property.attrib['Type'] }} &value)
{
int32_t indexToSet = GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.GetSize();
GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.PushBack(value);
@@ -134,24 +133,24 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}Clear(const Multi
GetParent().MarkDirty();
}
{% elif Property.attrib['Container'] == 'Object' %}
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput& inputCommand, const {{ Property.attrib['Type'] }}& value)
{% elif Property.attrib['Container'] == 'Object' %}
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Property.attrib['Type'] }}& value)
{
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }} != value)
{
Modify{{ UpperFirst(Property.attrib['Name']) }}(inputCommand) = value;
Modify{{ UpperFirst(Property.attrib['Name']) }}() = value;
}
}
{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&)
{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}()
{
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property) }}), true);
GetParent().MarkDirty();
return GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}{% if Property.attrib['IsRewindable']|booleanTrue %}.Modify(){% endif %};
}
{% else %}
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value)
{% else %}
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Property.attrib['Type'] }}& value)
{
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }} != value)
{
@@ -161,7 +160,6 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multipl
}
}
{% endif %}
{% endif %}
{% endmacro %}
{#
@@ -273,7 +271,7 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Prop
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
{% if Property.attrib['IsPublic'] | booleanTrue != IsProtected %}
{{ DefineNetworkPropertyGet(ClassName, Property, "GetParent().") }}
{{ DefineNetworkPropertyPredictableSet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) }}
{{ DefineNetworkPropertySet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) }}
{% endif %}
{% endcall %}
{% endmacro %}
@@ -478,6 +476,7 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re
{%- if networkPropertyCount.update({'value': networkPropertyCount.value + 1}) %}{% endif -%}
{% endcall %}
{% if networkPropertyCount.value > 0 %}
MultiplayerStats& stats = AZ::Interface<IMultiplayer>::Get()->GetStats();
// We modify the record if we are writing an update so that we don't notify for a change that really didn't change the value (just a duplicated send from the server)
[[maybe_unused]] bool modifyRecord = serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject;
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
@@ -509,7 +508,8 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re
static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property) }}),
m_{{ LowerFirst(Property.attrib['Name']) }},
"{{ Property.attrib['Name'] }}",
GetNetComponentId()
GetNetComponentId(),
stats
);
{% endif %}
{% endcall %}
@@ -1111,23 +1111,29 @@ namespace {{ Component.attrib['Namespace'] }}
{{ DefineNetworkPropertyReflection(Component, 'Authority', 'Client', ComponentBaseName)|indent(16) -}}
{{ DefineNetworkPropertyReflection(Component, 'Authority', 'Autonomous', ComponentBaseName)|indent(16) -}}
{{ DefineNetworkPropertyReflection(Component, 'Autonomous', 'Authority', ComponentBaseName)|indent(16) }}
{{ DefineArchetypePropertyReflection(Component, ComponentBaseName)|indent(16) }}
;
{{ DefineArchetypePropertyReflection(Component, ComponentBaseName)|indent(16) }};
}
ReflectToEditContext(context);
}
void {{ ComponentBaseName }}::{{ ComponentBaseName }}::ReflectToEditContext(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<{{ ComponentBaseName }}>("{{ ComponentName }}", "{{ Component.attrib['Description'] }}")
editContext->Class<{{ ComponentName }}>("{{ ComponentName }}", "{{ Component.attrib['Description'] }}")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Category, "Multiplayer")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Authority', ComponentBaseName)|indent(20) -}}
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Server', ComponentBaseName)|indent(20) -}}
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Client', ComponentBaseName)|indent(20) -}}
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Autonomous', ComponentBaseName)|indent(20) -}}
{{ DefineNetworkPropertyEditReflection(Component, 'Autonomous', 'Authority', ComponentBaseName)|indent(20) }}
{{ DefineArchetypePropertyEditReflection(Component, ComponentBaseName)|indent(20) }}
;
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Authority', ComponentName)|indent(20) -}}
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Server', ComponentName)|indent(20) -}}
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Client', ComponentName)|indent(20) -}}
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Autonomous', ComponentName)|indent(20) -}}
{{ DefineNetworkPropertyEditReflection(Component, 'Autonomous', 'Authority', ComponentName)|indent(20) }}
{{ DefineArchetypePropertyEditReflection(Component, ComponentName)|indent(20) }};
}
}
}
@@ -16,7 +16,7 @@
<Include File="Source/NetworkInput/NetworkInputVector.h"/>
<Include File="AzNetworking/DataStructures/ByteBuffer.h"/>
<NetworkProperty Type="Multiplayer::NetworkInputId" Name="LastInputId" Init="Multiplayer::NetworkInputId{0}" ReplicateFrom="Authority" ReplicateTo="Authority" IsRewindable="false" IsPredictable="false" IsPublic="false" Container="Object" ExposeToEditor="false" GenerateEventBindings="false" />
<NetworkProperty Type="Multiplayer::ClientInputId" Name="LastInputId" Init="Multiplayer::ClientInputId{0}" ReplicateFrom="Authority" ReplicateTo="Authority" IsRewindable="false" IsPredictable="false" IsPublic="false" Container="Object" ExposeToEditor="false" GenerateEventBindings="false" />
<RemoteProcedure Name="SendClientInput" InvokeFrom="Autonomous" HandleOn="Authority" IsPublic="true" IsReliable="false" Description="Client to server move / input RPC">
<Param Type="Multiplayer::NetworkInputVector" Name="inputArray" />
@@ -25,7 +25,7 @@
</RemoteProcedure>
<RemoteProcedure Name="SendClientInputCorrection" InvokeFrom="Authority" HandleOn="Autonomous" IsPublic="true" IsReliable="false" Description="Autonomous proxy correction RPC">
<Param Type="Multiplayer::NetworkInputId" Name="inputId" />
<Param Type="Multiplayer::ClientInputId" Name="inputId" />
<Param Type="AzNetworking::PacketEncodingBuffer" Name="correction" />
</RemoteProcedure>
@@ -24,7 +24,6 @@ namespace Multiplayer
serializeContext->Class<LocalPredictionPlayerInputComponent, LocalPredictionPlayerInputComponentBase>()
->Version(1);
}
LocalPredictionPlayerInputComponentBase::Reflect(context);
}
@@ -48,7 +47,7 @@ namespace Multiplayer
void LocalPredictionPlayerInputComponentController::HandleSendClientInputCorrection
(
[[maybe_unused]] const Multiplayer::NetworkInputId& inputId,
[[maybe_unused]] const Multiplayer::ClientInputId& inputId,
[[maybe_unused]] const AzNetworking::PacketEncodingBuffer& correction
)
{
@@ -42,6 +42,6 @@ namespace Multiplayer
void HandleSendClientInput(const Multiplayer::NetworkInputVector& inputArray, const uint32_t& stateHash, const AzNetworking::PacketEncodingBuffer& clientState) override;
void HandleSendMigrateClientInput(const Multiplayer::MigrateNetworkInputVector& inputArray) override;
void HandleSendClientInputCorrection(const Multiplayer::NetworkInputId& inputId, const AzNetworking::PacketEncodingBuffer& correction) override;
void HandleSendClientInputCorrection(const Multiplayer::ClientInputId& inputId, const AzNetworking::PacketEncodingBuffer& correction) override;
};
}
@@ -43,8 +43,12 @@ namespace Multiplayer
NetEntityId MultiplayerComponent::GetNetEntityId() const
{
const NetBindComponent* netBindComponent = GetNetBindComponent();
return netBindComponent ? netBindComponent->GetNetEntityId() : InvalidNetEntityId;
return m_netBindComponent ? m_netBindComponent->GetNetEntityId() : InvalidNetEntityId;
}
NetEntityRole MultiplayerComponent::GetNetEntityRole() const
{
return m_netBindComponent ? m_netBindComponent->GetNetEntityRole() : NetEntityRole::InvalidRole;
}
ConstNetworkEntityHandle MultiplayerComponent::GetEntityHandle() const
@@ -62,6 +62,7 @@ namespace Multiplayer
//! @}
NetEntityId GetNetEntityId() const;
NetEntityRole GetNetEntityRole() const;
ConstNetworkEntityHandle GetEntityHandle() const;
NetworkEntityHandle GetEntityHandle();
void MarkDirty();
@@ -109,7 +110,8 @@ namespace Multiplayer
int32_t bitIndex,
TYPE& value,
const char* name,
[[maybe_unused]] NetComponentId componentId
[[maybe_unused]] NetComponentId componentId,
MultiplayerStats& stats
)
{
if (bitset.GetBit(bitIndex))
@@ -119,6 +121,7 @@ namespace Multiplayer
serializer.Serialize(value, name);
if (modifyRecord && !serializer.GetTrackedChangesFlag())
{
// If the serializer didn't change any values, then lower the flag so we don't unnecessarily notify
bitset.SetBit(bitIndex, false);
}
const uint32_t postUpdateSize = serializer.GetSize();
@@ -126,8 +129,7 @@ namespace Multiplayer
const uint32_t updateSize = (postUpdateSize - prevUpdateSize);
if (updateSize > 0)
{
MultiplayerStats& stats = AZ::Interface<IMultiplayer>::Get()->GetStats();
if (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject)
if (modifyRecord)
{
stats.m_propertyUpdatesRecv++;
stats.m_propertyUpdatesRecvBytes += updateSize;
@@ -27,6 +27,11 @@ namespace Multiplayer
return m_owner.GetNetEntityId();
}
NetEntityRole MultiplayerController::GetNetEntityRole() const
{
return GetNetBindComponent()->GetNetEntityRole();
}
AZ::Entity* MultiplayerController::GetEntity() const
{
return m_owner.GetEntity();
@@ -47,6 +47,10 @@ namespace Multiplayer
//! @return the networkId for the entity that owns this controller
NetEntityId GetNetEntityId() const;
//! Returns the networkRole for the entity that owns this controller.
//! @return the networkRole for the entity that owns this controller
NetEntityRole GetNetEntityRole() const;
//! Returns the raw AZ::Entity pointer for the entity that owns this controller.
//! @return the raw AZ::Entity pointer for the entity that owns this controller
AZ::Entity* GetEntity() const;
@@ -13,6 +13,8 @@
#include <Source/Components/NetworkTransformComponent.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/EBus/IEventScheduler.h>
#include <AzFramework/Components/TransformComponent.h>
namespace Multiplayer
{
@@ -24,7 +26,81 @@ namespace Multiplayer
serializeContext->Class<NetworkTransformComponent, NetworkTransformComponentBase>()
->Version(1);
}
NetworkTransformComponentBase::Reflect(context);
}
NetworkTransformComponent::NetworkTransformComponent()
: m_rotationEventHandler([this](const AZ::Quaternion& rotation) { OnRotationChangedEvent(rotation); })
, m_translationEventHandler([this](const AZ::Vector3& translation) { OnTranslationChangedEvent(translation); })
, m_scaleEventHandler([this](const AZ::Vector3& scale) { OnScaleChangedEvent(scale); })
{
;
}
void NetworkTransformComponent::OnInit()
{
;
}
void NetworkTransformComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
{
RotationAddEvent(m_rotationEventHandler);
TranslationAddEvent(m_translationEventHandler);
ScaleAddEvent(m_scaleEventHandler);
}
void NetworkTransformComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
{
;
}
void NetworkTransformComponent::OnRotationChangedEvent(const AZ::Quaternion& rotation)
{
AZ::Transform worldTm = GetTransformComponent()->GetWorldTM();
worldTm.SetRotation(rotation);
GetTransformComponent()->SetWorldTM(worldTm);
}
void NetworkTransformComponent::OnTranslationChangedEvent(const AZ::Vector3& translation)
{
AZ::Transform worldTm = GetTransformComponent()->GetWorldTM();
worldTm.SetTranslation(translation);
GetTransformComponent()->SetWorldTM(worldTm);
}
void NetworkTransformComponent::OnScaleChangedEvent(const AZ::Vector3& scale)
{
AZ::Transform worldTm = GetTransformComponent()->GetWorldTM();
worldTm.SetScale(scale);
GetTransformComponent()->SetWorldTM(worldTm);
}
NetworkTransformComponentController::NetworkTransformComponentController(NetworkTransformComponent& parent)
: NetworkTransformComponentControllerBase(parent)
, m_transformChangedHandler([this](const AZ::Transform&, const AZ::Transform& worldTm) { OnTransformChangedEvent(worldTm); })
{
;
}
void NetworkTransformComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
{
GetParent().GetTransformComponent()->BindTransformChangedEventHandler(m_transformChangedHandler);
OnTransformChangedEvent(GetParent().GetTransformComponent()->GetWorldTM());
}
void NetworkTransformComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
{
;
}
void NetworkTransformComponentController::OnTransformChangedEvent(const AZ::Transform& worldTm)
{
if (GetNetEntityRole() == NetEntityRole::Authority)
{
SetRotation(worldTm.GetRotation());
SetTranslation(worldTm.GetTranslation());
SetScale(worldTm.GetScale());
}
}
}
@@ -13,6 +13,7 @@
#pragma once
#include <Source/AutoGen/NetworkTransformComponent.AutoComponent.h>
#include <AzCore/Component/TransformBus.h>
namespace Multiplayer
{
@@ -22,20 +23,36 @@ namespace Multiplayer
public:
AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkTransformComponent, s_networkTransformComponentConcreteUuid, Multiplayer::NetworkTransformComponentBase);
static void Reflect([[maybe_unused]] AZ::ReflectContext* context);
static void Reflect(AZ::ReflectContext* context);
void OnInit() override {}
void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
NetworkTransformComponent();
void OnInit() override;
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
private:
void OnRotationChangedEvent(const AZ::Quaternion& rotation);
void OnTranslationChangedEvent(const AZ::Vector3& translation);
void OnScaleChangedEvent(const AZ::Vector3& scale);
AZ::Event<AZ::Quaternion>::Handler m_rotationEventHandler;
AZ::Event<AZ::Vector3>::Handler m_translationEventHandler;
AZ::Event<AZ::Vector3>::Handler m_scaleEventHandler;
};
class NetworkTransformComponentController
: public NetworkTransformComponentControllerBase
{
public:
NetworkTransformComponentController(NetworkTransformComponent& parent) : NetworkTransformComponentControllerBase(parent) {}
NetworkTransformComponentController(NetworkTransformComponent& parent);
void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
private:
void OnTransformChangedEvent(const AZ::Transform& worldTm);
AZ::TransformChangedEvent::Handler m_transformChangedHandler;
};
}
@@ -0,0 +1,59 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Source/ConnectionData/ClientToServerConnectionData.h>
namespace Multiplayer
{
static constexpr uint32_t Uint32Max = AZStd::numeric_limits<uint32_t>::max();
// This can be used to help mitigate client side performance when large numbers of entities are created off the network
AZ_CVAR(uint32_t, cl_ClientMaxRemoteEntitiesPendingCreationCount, Uint32Max, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Maximum number of entities that we have sent to the client, but have not had a confirmation back from the client");
AZ_CVAR(AZ::TimeMs, cl_ClientEntityReplicatorPendingRemovalTimeMs, AZ::TimeMs{ 10000 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "How long should wait prior to removing an entity for the client through a change in the replication window, entity deletes are still immediate");
ClientToServerConnectionData::ClientToServerConnectionData
(
AzNetworking::IConnection* connection,
AzNetworking::IConnectionListener& connectionListener
)
: m_connection(connection)
, m_entityReplicationManager(*connection, connectionListener, EntityReplicationManager::Mode::LocalClientToRemoteServer)
{
m_entityReplicationManager.SetMaxRemoteEntitiesPendingCreationCount(cl_ClientMaxRemoteEntitiesPendingCreationCount);
m_entityReplicationManager.SetEntityPendingRemovalMs(cl_ClientEntityReplicatorPendingRemovalTimeMs);
}
ClientToServerConnectionData::~ClientToServerConnectionData()
{
m_entityReplicationManager.Clear(false);
}
ConnectionDataType ClientToServerConnectionData::GetConnectionDataType() const
{
return ConnectionDataType::ClientToServer;
}
AzNetworking::IConnection* ClientToServerConnectionData::GetConnection() const
{
return m_connection;
}
EntityReplicationManager& ClientToServerConnectionData::GetReplicationManager()
{
return m_entityReplicationManager;
}
void ClientToServerConnectionData::Update([[maybe_unused]] AZ::TimeMs serverGameTimeMs)
{
m_entityReplicationManager.ActivatePendingEntities();
}
}
@@ -0,0 +1,47 @@
/*
* 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 <Source/ConnectionData/IConnectionData.h>
namespace Multiplayer
{
class ClientToServerConnectionData final
: public IConnectionData
{
public:
ClientToServerConnectionData
(
AzNetworking::IConnection* connection,
AzNetworking::IConnectionListener& connectionListener
);
~ClientToServerConnectionData() override;
//! IConnectionData interface
//! @{
ConnectionDataType GetConnectionDataType() const override;
AzNetworking::IConnection* GetConnection() const override;
EntityReplicationManager& GetReplicationManager() override;
void Update(AZ::TimeMs serverGameTimeMs) override;
//! @}
bool CanSendUpdates();
private:
EntityReplicationManager m_entityReplicationManager;
AzNetworking::IConnection* m_connection = nullptr;
bool m_canSendUpdates = true;
};
}
#include <Source/ConnectionData/ClientToServerConnectionData.inl>
@@ -0,0 +1,19 @@
/*
* 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.
*
*/
namespace Multiplayer
{
inline bool ClientToServerConnectionData::CanSendUpdates()
{
return m_canSendUpdates;
}
}
@@ -19,6 +19,7 @@ namespace Multiplayer
{
enum class ConnectionDataType
{
ClientToServer,
ServerToClient,
ServerToServer
};
@@ -13,7 +13,9 @@
#include <Source/MultiplayerSystemComponent.h>
#include <Source/Components/MultiplayerComponent.h>
#include <Source/AutoGen/AutoComponentTypes.h>
#include <Source/ConnectionData/ClientToServerConnectionData.h>
#include <Source/ConnectionData/ServerToClientConnectionData.h>
#include <Source/ReplicationWindows/NullReplicationWindow.h>
#include <Source/ReplicationWindows/ServerToClientReplicationWindow.h>
#include <Source/EntityDomains/FullOwnershipEntityDomain.h>
#include <AzNetworking/Framework/INetworking.h>
@@ -66,6 +68,7 @@ namespace Multiplayer
AZ_CVAR(AZ::CVarFixedString, sv_gamerules, "norules", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "GameRules server works with");
AZ_CVAR(ProtocolType, sv_protocol, ProtocolType::Udp, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "This flag controls whether we use TCP or UDP for game networking");
AZ_CVAR(bool, sv_isDedicated, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether the host command creates an independent or client hosted server");
AZ_CVAR(AZ::TimeMs, cl_defaultNetworkEntityActivationTimeSliceMs, AZ::TimeMs{ 0 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Max Ms to use to activate entities coming from the network, 0 means instantiate everything");
void MultiplayerSystemComponent::Reflect(AZ::ReflectContext* context)
{
@@ -126,24 +129,27 @@ namespace Multiplayer
// Handle deferred local rpc messages that were generated during the updates
m_networkEntityManager.DispatchLocalDeferredRpcMessages();
m_networkEntityManager.NotifyEntitiesChanged();
// Let the network system know the frame is done and we can collect dirty bits
m_networkEntityManager.NotifyEntitiesDirtied();
// Send out the game state update to all connections
{
auto sendNetworkUpdates = [serverGameTimeMs](IConnection& connection)
{
if (connection.GetUserData() != nullptr)
{
IConnectionData* connectionData = reinterpret_cast<IConnectionData*>(connection.GetUserData());
connectionData->Update(serverGameTimeMs);
}
};
m_networkInterface->GetConnectionSet().VisitConnections(sendNetworkUpdates);
}
MultiplayerStats& stats = GetStats();
stats.m_entityCount = GetNetworkEntityManager()->GetEntityCount();
auto sendNetworkUpdates = [serverGameTimeMs](IConnection& connection)
{
if (connection.GetUserData() != nullptr)
{
IConnectionData* connectionData = reinterpret_cast<IConnectionData*>(connection.GetUserData());
connectionData->Update(serverGameTimeMs);
}
};
// Send out the game state update to all connections
m_networkInterface->GetConnectionSet().VisitConnections(sendNetworkUpdates);
MultiplayerPackets::SyncConsole packet;
AZ::ThreadSafeDeque<AZStd::string>::DequeType cvarUpdates;
m_cvarCommands.Swap(cvarUpdates);
@@ -245,12 +251,8 @@ namespace Multiplayer
AZ::CVarFixedString commandString = "sv_map " + packet.GetMap();
AZ::Interface<AZ::IConsole>::Get()->PerformCommand(commandString.c_str());
// This is a bit tricky, so it warrants extra commenting
// The cry level loader has a 'map' command used to invoke the level load system
// We don't want any explicit cry dependencies, so instead we rely on the
// az console binding inside SystemInit to echo any unhandled commands to
// the cry console by stripping off the prefix 'sv_'
AZ::Interface<AZ::IConsole>::Get()->PerformCommand(commandString.c_str() + 3);
AZ::CVarFixedString loadLevelString = "LoadLevel " + packet.GetMap();
AZ::Interface<AZ::IConsole>::Get()->PerformCommand(loadLevelString.c_str());
return true;
}
@@ -410,6 +412,16 @@ namespace Multiplayer
AZStd::unique_ptr<IReplicationWindow> window = AZStd::make_unique<ServerToClientReplicationWindow>(controlledEntity, connection);
reinterpret_cast<ServerToClientConnectionData*>(connection->GetUserData())->GetReplicationManager().SetReplicationWindow(AZStd::move(window));
}
else
{
if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so
{
connection->SetUserData(new ClientToServerConnectionData(connection, *this));
}
AZStd::unique_ptr<IReplicationWindow> window = AZStd::make_unique<NullReplicationWindow>();
reinterpret_cast<ServerToClientConnectionData*>(connection->GetUserData())->GetReplicationManager().SetEntityActivationTimeSliceMs(cl_defaultNetworkEntityActivationTimeSliceMs);
}
}
bool MultiplayerSystemComponent::OnPacketReceived(AzNetworking::IConnection* connection, const IPacketHeader& packetHeader, ISerializer& serializer)
@@ -463,6 +475,7 @@ namespace Multiplayer
}
}
m_agentType = multiplayerType;
AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType));
}
void MultiplayerSystemComponent::AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler)
@@ -535,14 +548,15 @@ namespace Multiplayer
void host([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
{
Multiplayer::MultiplayerAgentType serverType = sv_isDedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer;
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(serverType);
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName));
networkInterface->Listen(sv_port);
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(serverType);
}
AZ_CONSOLEFREEFUNC(host, AZ::ConsoleFunctorFlags::DontReplicate, "Opens a multiplayer connection as a host for other clients to connect to");
void connect([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
{
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Client);
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName));
if (arguments.size() < 1)
@@ -567,12 +581,12 @@ namespace Multiplayer
int32_t portNumber = atol(portStr);
const IpAddress ipAddress(addressStr, aznumeric_cast<uint16_t>(portNumber), networkInterface->GetType());
networkInterface->Connect(ipAddress);
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Client);
}
AZ_CONSOLEFREEFUNC(connect, AZ::ConsoleFunctorFlags::DontReplicate, "Opens a multiplayer connection to a remote host");
void disconnect([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
{
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Uninitialized);
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName));
auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); };
networkInterface->GetConnectionSet().VisitConnections(visitor);
@@ -21,8 +21,8 @@
#include <AzNetworking/ConnectionLayer/IConnectionListener.h>
#include <Include/IMultiplayer.h>
#include <Source/NetworkTime/NetworkTime.h>
#include <Source/AutoGen/Multiplayer.AutoPacketDispatcher.h>
#include <Source/NetworkEntity/NetworkEntityManager.h>
#include <Source/AutoGen/Multiplayer.AutoPacketDispatcher.h>
namespace AzNetworking
{
@@ -25,6 +25,7 @@
#include <AzNetworking/PacketLayer/IPacketHeader.h>
#include <AzNetworking/Serialization/NetworkInputSerializer.h>
#include <AzNetworking/Serialization/NetworkOutputSerializer.h>
#include <AzNetworking/Serialization/TrackChangedSerializer.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Console/IConsole.h>
#include <AzCore/Console/ILogger.h>
@@ -126,9 +127,9 @@ namespace Multiplayer
MultiplayerPackets::EntityUpdates entityUpdatePacket;
entityUpdatePacket.SetHostTimeMs(serverGameTimeMs);
// Serialize everything
for (auto it = toSendList.begin(); it != toSendList.end();)
while (!toSendList.empty())
{
EntityReplicator* replicator = *it;
EntityReplicator* replicator = toSendList.front();
NetworkEntityUpdateMessage updateMessage(replicator->GenerateUpdatePacket());
const uint32_t nextMessageSize = updateMessage.GetEstimatedSerializeSize();
@@ -144,15 +145,15 @@ namespace Multiplayer
pendingPacketSize += nextMessageSize;
entityUpdatePacket.ModifyEntityMessages().push_back(updateMessage);
replicatorUpdatedList.push_back(*it);
it = toSendList.erase(it);
replicatorUpdatedList.push_back(replicator);
toSendList.pop_front();
if (largeEntityDetected)
{
AZLOG_WARN("\n\n*******************************");
AZLOG_WARN
(
"Serializing Extremely Large Entity (%u) - MaxPayload: %d NeededSize %d",
"Serializing extremely large entity (%u) - MaxPayload: %d NeededSize %d",
aznumeric_cast<uint32_t>(replicator->GetEntityHandle().GetNetEntityId()),
maxPayloadSize,
nextMessageSize
@@ -173,16 +174,16 @@ namespace Multiplayer
EntityReplicationManager::EntityReplicatorList EntityReplicationManager::GenerateEntityUpdateList()
{
if (m_replicationWindow == nullptr)
{
return EntityReplicatorList();
}
// Generate a list of all our entities that need updates
EntityReplicatorList autonomousReplicators;
autonomousReplicators.reserve(m_replicatorsPendingSend.size());
EntityReplicatorList proxyReplicators;
proxyReplicators.reserve(m_replicatorsPendingSend.size());
EntityReplicatorList toSendList;
uint32_t elementsAdded = 0;
for (auto iter = m_replicatorsPendingSend.begin();
iter != m_replicatorsPendingSend.end()
&& elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount();)
for (auto iter = m_replicatorsPendingSend.begin(); iter != m_replicatorsPendingSend.end() && elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount(); )
{
EntityReplicator* replicator = GetEntityReplicator(*iter);
bool clearPendingSend = true;
@@ -218,13 +219,13 @@ namespace Multiplayer
if (replicator->GetRemoteNetworkRole() == NetEntityRole::Autonomous)
{
autonomousReplicators.push_back(replicator);
toSendList.push_back(replicator);
}
else
{
if (elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount())
{
proxyReplicators.push_back(replicator);
toSendList.push_back(replicator);
}
}
}
@@ -243,9 +244,6 @@ namespace Multiplayer
}
}
EntityReplicatorList toSendList;
toSendList.swap(autonomousReplicators);
toSendList.insert(toSendList.end(), proxyReplicators.begin(), proxyReplicators.end());
return toSendList;
}
@@ -543,6 +541,7 @@ namespace Multiplayer
// Create an entity if we don't have one
if (createEntity)
{
// @pereslav
//replicatorEntity = GetNetworkEntityManager()->CreateSingleEntityImmediateInternal(prefabEntityId, EntitySpawnType::Replicate, AutoActivate::DoNotActivate, netEntityId, localNetworkRole, AZ::Transform::Identity());
AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab");// %s", prefabEntityId.GetString());
if (replicatorEntity == nullptr)
@@ -765,7 +764,7 @@ namespace Multiplayer
return HandleEntityDeleteMessage(entityReplicator, packetHeader, updateMessage);
}
AzNetworking::NetworkOutputSerializer outputSerializer(updateMessage.GetData()->GetBuffer(), updateMessage.GetData()->GetSize());
AzNetworking::TrackChangedSerializer<AzNetworking::NetworkOutputSerializer> outputSerializer(updateMessage.GetData()->GetBuffer(), updateMessage.GetData()->GetSize());
PrefabEntityId prefabEntityId;
if (updateMessage.GetHasValidPrefabId())
@@ -1125,7 +1124,7 @@ namespace Multiplayer
{
if (message.GetPropertyUpdateData().GetSize() > 0)
{
AzNetworking::NetworkOutputSerializer outputSerializer(message.ModifyPropertyUpdateData().GetBuffer(), message.ModifyPropertyUpdateData().GetSize());
AzNetworking::TrackChangedSerializer<AzNetworking::NetworkOutputSerializer> outputSerializer(message.ModifyPropertyUpdateData().GetBuffer(), message.ModifyPropertyUpdateData().GetSize());
if (!HandlePropertyChangeMessage
(
replicator,
@@ -22,6 +22,7 @@
#include <AzNetworking/PacketLayer/IPacketHeader.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/containers/deque.h>
#include <AzCore/std/limits.h>
#include <AzCore/EBus/Event.h>
#include <AzCore/EBus/ScheduledEvent.h>
@@ -114,7 +115,7 @@ namespace Multiplayer
using RpcMessages = AZStd::list<NetworkEntityRpcMessage>;
bool DispatchOrphanedRpc(NetworkEntityRpcMessage& message, EntityReplicator* entityReplicator);
using EntityReplicatorList = AZStd::vector<EntityReplicator*>;
using EntityReplicatorList = AZStd::deque<EntityReplicator*>;
EntityReplicatorList GenerateEntityUpdateList();
void SendEntityUpdatesPacketHelper(AZ::TimeMs serverGameTimeMs, EntityReplicatorList& toSendList, uint32_t maxPayloadSize, AzNetworking::IConnection& connection);
@@ -283,7 +283,7 @@ namespace Multiplayer
AZ_Assert(netBindComponent, "No Multiplayer::NetBindComponent");
bool isAuthority = (GetBoundLocalNetworkRole() == NetEntityRole::Authority)
&& (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole());
&& (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole());
bool isClient = GetRemoteNetworkRole() == NetEntityRole::Client;
bool isAutonomous = GetBoundLocalNetworkRole() == NetEntityRole::Autonomous;
if (isAuthority || isClient || isAutonomous)
@@ -311,9 +311,9 @@ namespace Multiplayer
{
bool ret(false);
bool isServer = (GetBoundLocalNetworkRole() == NetEntityRole::Server)
&& (GetRemoteNetworkRole() == NetEntityRole::Authority);
&& (GetRemoteNetworkRole() == NetEntityRole::Authority);
bool isClient = (GetBoundLocalNetworkRole() == NetEntityRole::Client)
|| (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous);
|| (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous);
if (isServer || isClient)
{
ret = true;
@@ -12,6 +12,7 @@
#include <Source/NetworkEntity/NetworkEntityManager.h>
#include <Source/Components/NetBindComponent.h>
#include <Include/IMultiplayer.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/Console/IConsole.h>
#include <AzCore/Console/ILogger.h>
@@ -34,6 +35,12 @@ namespace Multiplayer
, m_entityRemovedEventHandler([this](AZ::Entity* entity) { OnEntityRemoved(entity); })
{
AZ::Interface<INetworkEntityManager>::Register(this);
if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr)
{
// Null guard needed for unit tests
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler);
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler);
}
}
NetworkEntityManager::~NetworkEntityManager()
@@ -43,13 +50,6 @@ namespace Multiplayer
void NetworkEntityManager::Initialize(HostId hostId, AZStd::unique_ptr<IEntityDomain> entityDomain)
{
if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr)
{
// Null guard needed for unit tests
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler);
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler);
}
m_hostId = hostId;
m_entityDomain = AZStd::move(entityDomain);
m_updateEntityDomainEvent.Enqueue(net_EntityDomainUpdateMs, true);
@@ -282,8 +282,13 @@ namespace Multiplayer
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
if (netBindComponent != nullptr)
{
// @pereslav
// Note that this is a total hack.. we should not be listening to this event on a client
// Entities should instead be spawned by the prefabEntityId inside EntityReplicationManager::HandlePropertyChangeMessage()
const bool isClient = AZ::Interface<IMultiplayer>::Get()->GetAgentType() == MultiplayerAgentType::Client;
const NetEntityRole netEntityRole = isClient ? NetEntityRole::Client: NetEntityRole::Authority;
const NetEntityId netEntityId = m_nextEntityId++;
netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, NetEntityRole::Authority);
netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, netEntityRole);
}
}
@@ -33,22 +33,36 @@ namespace Multiplayer
return *this;
}
void NetworkInput::SetNetworkInputId(NetworkInputId inputId)
void NetworkInput::SetClientInputId(ClientInputId inputId)
{
m_inputId = inputId;
}
NetworkInputId NetworkInput::GetNetworkInputId() const
ClientInputId NetworkInput::GetClientInputId() const
{
return m_inputId;
}
NetworkInputId& NetworkInput::ModifyNetworkInputId()
ClientInputId& NetworkInput::ModifyClientInputId()
{
return m_inputId;
}
void NetworkInput::SetServerTimeMs(AZ::TimeMs serverTimeMs)
{
m_serverTimeMs = serverTimeMs;
}
AZ::TimeMs NetworkInput::GetServerTimeMs() const
{
return m_serverTimeMs;
}
AZ::TimeMs& NetworkInput::ModifyServerTimeMs()
{
return m_serverTimeMs;
}
void NetworkInput::AttachNetBindComponent(NetBindComponent* netBindComponent)
{
m_wasAttached = true;
@@ -62,7 +76,6 @@ namespace Multiplayer
bool NetworkInput::Serialize(AzNetworking::ISerializer& serializer)
{
//static_assert(UINT8_MAX >= Multiplayer::ComponentTypes::c_Count, "Expected fewer than 255 components, this code needs to be updated");
if (!serializer.Serialize(m_inputId, "InputId"))
{
return false;
@@ -135,8 +148,9 @@ namespace Multiplayer
void NetworkInput::CopyInternal(const NetworkInput& rhs)
{
m_inputId = rhs.m_inputId;
m_serverTimeMs = rhs.m_serverTimeMs;
m_componentInputs.resize(rhs.m_componentInputs.size());
for (int i = 0; i < rhs.m_componentInputs.size(); ++i)
for (int32_t i = 0; i < rhs.m_componentInputs.size(); ++i)
{
if (m_componentInputs[i] == nullptr || m_componentInputs[i]->GetComponentId() != rhs.m_componentInputs[i]->GetComponentId())
{
@@ -21,7 +21,7 @@ namespace Multiplayer
// Forwards
class NetBindComponent;
AZ_TYPE_SAFE_INTEGRAL(NetworkInputId, uint16_t);
AZ_TYPE_SAFE_INTEGRAL(ClientInputId, uint16_t);
//! @class NetworkInput
//! @brief A single networked client input command.
@@ -38,9 +38,13 @@ namespace Multiplayer
NetworkInput(const NetworkInput&);
NetworkInput& operator= (const NetworkInput&);
void SetNetworkInputId(NetworkInputId inputId);
NetworkInputId GetNetworkInputId() const;
NetworkInputId& ModifyNetworkInputId();
void SetClientInputId(ClientInputId inputId);
ClientInputId GetClientInputId() const;
ClientInputId& ModifyClientInputId();
void SetServerTimeMs(AZ::TimeMs serverTimeMs);
AZ::TimeMs GetServerTimeMs() const;
AZ::TimeMs& ModifyServerTimeMs();
void AttachNetBindComponent(NetBindComponent* netBindComponent);
@@ -67,10 +71,11 @@ namespace Multiplayer
void CopyInternal(const NetworkInput& rhs);
MultiplayerComponentInputVector m_componentInputs;
NetworkInputId m_inputId = NetworkInputId{ 0 };
ClientInputId m_inputId = ClientInputId{ 0 };
AZ::TimeMs m_serverTimeMs = AZ::TimeMs{ 0 };
ConstNetworkEntityHandle m_owner;
bool m_wasAttached = false;
};
}
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::NetworkInputId);
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::ClientInputId);
@@ -48,12 +48,12 @@ namespace Multiplayer
return m_inputs[index].m_networkInput;
}
void NetworkInputVector::SetPreviousInputId(NetworkInputId previousInputId)
void NetworkInputVector::SetPreviousInputId(ClientInputId previousInputId)
{
m_previousInputId = previousInputId;
}
NetworkInputId NetworkInputVector::GetPreviousInputId() const
ClientInputId NetworkInputVector::GetPreviousInputId() const
{
return m_previousInputId;
}
@@ -32,8 +32,8 @@ namespace Multiplayer
NetworkInput& operator[](uint32_t index);
const NetworkInput& operator[](uint32_t index) const;
void SetPreviousInputId(NetworkInputId previousInputId);
NetworkInputId GetPreviousInputId() const;
void SetPreviousInputId(ClientInputId previousInputId);
ClientInputId GetPreviousInputId() const;
bool Serialize(AzNetworking::ISerializer& serializer);
@@ -48,7 +48,7 @@ namespace Multiplayer
ConstNetworkEntityHandle m_owner;
AZStd::fixed_vector<Wrapper, MaxElements> m_inputs;
NetworkInputId m_previousInputId;
ClientInputId m_previousInputId;
};
//! @class MigrateNetworkInputVector
@@ -73,7 +73,7 @@ namespace Multiplayer
template <typename BASE_TYPE, AZStd::size_t REWIND_SIZE>
inline BASE_TYPE& RewindableObject<BASE_TYPE, REWIND_SIZE>::Modify()
{
ApplicationFrameId frameTime = GetCurrentTimeForProperty();
const ApplicationFrameId frameTime = GetCurrentTimeForProperty();
if (frameTime < m_headTime)
{
AZ_Assert(false, "Trying to mutate a rewindable in the past");
@@ -82,7 +82,7 @@ namespace Multiplayer
{
SetValueForTime(GetValueForTime(frameTime), frameTime);
}
const BASE_TYPE& returnValue = GetValueForTime(GetCurrentTimeForProperty());
const BASE_TYPE& returnValue = GetValueForTime(frameTime);
return const_cast<BASE_TYPE&>(returnValue);
}
@@ -103,10 +103,11 @@ namespace Multiplayer
template <typename BASE_TYPE, AZStd::size_t REWIND_SIZE>
inline bool RewindableObject<BASE_TYPE, REWIND_SIZE>::Serialize(AzNetworking::ISerializer& serializer)
{
BASE_TYPE current = GetValueForTime(GetCurrentTimeForProperty());
if (serializer.Serialize(current, "Element") && (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject))
const ApplicationFrameId frameTime = GetCurrentTimeForProperty();
BASE_TYPE value = GetValueForTime(frameTime);
if (serializer.Serialize(value, "Element") && (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject))
{
SetValueForTime(current, GetCurrentTimeForProperty());
SetValueForTime(value, frameTime);
}
return serializer.IsValid();
}
@@ -0,0 +1,47 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "NullReplicationWindow.h"
namespace Multiplayer
{
bool NullReplicationWindow::ReplicationSetUpdateReady()
{
return true;
}
const ReplicationSet& NullReplicationWindow::GetReplicationSet() const
{
return m_emptySet;
}
uint32_t NullReplicationWindow::GetMaxEntityReplicatorSendCount() const
{
return 0;
}
bool NullReplicationWindow::IsInWindow([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle, NetEntityRole& outNetworkRole) const
{
outNetworkRole = NetEntityRole::InvalidRole;
return false;
}
void NullReplicationWindow::UpdateWindow()
{
;
}
void NullReplicationWindow::DebugDraw() const
{
// Nothing to draw
}
}
@@ -0,0 +1,38 @@
/*
* 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 <Source/ReplicationWindows/IReplicationWindow.h>
namespace Multiplayer
{
class NullReplicationWindow
: public IReplicationWindow
{
public:
NullReplicationWindow() = default;
//! IReplicationWindow interface
//! @{
bool ReplicationSetUpdateReady() override;
const ReplicationSet& GetReplicationSet() const override;
uint32_t GetMaxEntityReplicatorSendCount() const override;
bool IsInWindow(const ConstNetworkEntityHandle& entityPtr, NetEntityRole& outNetworkRole) const override;
void UpdateWindow() override;
void DebugDraw() const override;
//! @}
private:
ReplicationSet m_emptySet;
};
}
@@ -202,8 +202,7 @@ namespace Multiplayer
void ServerToClientReplicationWindow::OnEntityActivated(const AZ::EntityId& entityId)
{
AZ::Entity* entity = nullptr;
EBUS_EVENT_RESULT(entity, AZ::ComponentApplicationBus, FindEntity, entityId);
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
ConstNetworkEntityHandle entityHandle(entity, GetNetworkEntityTracker());
NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent();
@@ -234,8 +233,7 @@ namespace Multiplayer
void ServerToClientReplicationWindow::OnEntityDeactivated(const AZ::EntityId& entityId)
{
AZ::Entity* entity = nullptr;
EBUS_EVENT_RESULT(entity, AZ::ComponentApplicationBus, FindEntity, entityId);
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
ConstNetworkEntityHandle entityHandle(entity, GetNetworkEntityTracker());
NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent();
@@ -97,6 +97,10 @@ namespace UnitTest
m_mpComponent->OnConnect(&connMock2);
EXPECT_EQ(m_connectionAcquiredCount, 25);
// Clean up connection data
m_mpComponent->OnDisconnect(&connMock1, AzNetworking::DisconnectReason::None, AzNetworking::TerminationEndpoint::Local);
m_mpComponent->OnDisconnect(&connMock2, AzNetworking::DisconnectReason::None, AzNetworking::TerminationEndpoint::Local);
}
}
@@ -34,6 +34,9 @@ set(FILES
Source/Components/NetBindComponent.h
Source/Components/NetworkTransformComponent.cpp
Source/Components/NetworkTransformComponent.h
Source/ConnectionData/ClientToServerConnectionData.cpp
Source/ConnectionData/ClientToServerConnectionData.h
Source/ConnectionData/ClientToServerConnectionData.inl
Source/ConnectionData/IConnectionData.h
Source/ConnectionData/ServerToClientConnectionData.cpp
Source/ConnectionData/ServerToClientConnectionData.h
@@ -81,6 +84,8 @@ set(FILES
Source/NetworkTime/NetworkTime.h
Source/NetworkTime/RewindableObject.h
Source/NetworkTime/RewindableObject.inl
Source/ReplicationWindows/NullReplicationWindow.cpp
Source/ReplicationWindows/NullReplicationWindow.h
Source/ReplicationWindows/IReplicationWindow.h
Source/ReplicationWindows/ServerToClientReplicationWindow.cpp
Source/ReplicationWindows/ServerToClientReplicationWindow.h
+3
View File
@@ -15,6 +15,7 @@
#include <AzFramework/Physics/CollisionBus.h>
#include <AzFramework/Physics/SystemBus.h>
#include <AzFramework/Physics/Configuration/CollisionConfiguration.h>
#include <AzFramework/Physics/Configuration/SceneConfiguration.h>
#include <AzToolsFramework/API/ViewPaneOptions.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <LyViewPaneNames.h>
@@ -23,6 +24,8 @@
#include <Editor/EditorWindow.h>
#include <Editor/ConfigurationWidget.h>
#include <System/PhysXSystem.h>
#include <PhysX/Configuration/PhysXConfiguration.h>
#include <PhysX/Debug/PhysXDebugConfiguration.h>
namespace PhysX
{
+7
View File
@@ -19,6 +19,7 @@
namespace AzPhysics
{
class CollisionConfiguration;
struct SceneConfiguration;
}
namespace Ui
@@ -28,6 +29,12 @@ namespace Ui
namespace PhysX
{
struct PhysXSystemConfiguration;
namespace Debug
{
struct DebugConfiguration;
}
namespace Editor
{
/// Window pane wrapper for the PhysX Configuration Widget.
@@ -18,13 +18,15 @@
#include <AzFramework/Physics/SystemBus.h>
#include <AzFramework/Physics/Collision/CollisionEvents.h>
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
#include <Editor/ConfigStringLineEditCtrl.h>
#include <Editor/EditorJointConfiguration.h>
#include <I3DEngine.h>
#include <IEditor.h>
#include <ISurfaceType.h>
#include <Editor/ConfigStringLineEditCtrl.h>
#include <Editor/EditorJointConfiguration.h>
#include <Editor/EditorWindow.h>
#include <Editor/PropertyTypes.h>
#include <System/PhysXSystem.h>
namespace PhysX
@@ -116,18 +118,20 @@ namespace PhysX
{
AzPhysics::SceneConfiguration editorWorldConfiguration = physicsSystem->GetDefaultSceneConfiguration();
editorWorldConfiguration.m_sceneName = AzPhysics::EditorPhysicsSceneName;
editorWorldConfiguration.m_sceneName = "EditorScene";
m_editorWorldSceneHandle = physicsSystem->AddScene(editorWorldConfiguration);
}
PhysX::RegisterConfigStringLineEditHandler(); // Register custom unique string line edit control
PhysX::Editor::RegisterPropertyTypes();
AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
}
void EditorSystemComponent::Deactivate()
{
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
Physics::EditorWorldBus::Handler::BusDisconnect();
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
@@ -164,6 +168,16 @@ namespace PhysX
}
}
void EditorSystemComponent::PopulateEditorGlobalContextMenu([[maybe_unused]] QMenu* menu, [[maybe_unused]] const AZ::Vector2& point, [[maybe_unused]] int flags)
{
}
void EditorSystemComponent::NotifyRegisterViews()
{
PhysX::Editor::EditorWindow::RegisterViewClass();
}
AZ::Data::AssetId EditorSystemComponent::GenerateSurfaceTypesLibrary()
{
AZ::Data::AssetId resultAssetId;
@@ -30,6 +30,7 @@ namespace PhysX
: public AZ::Component
, public Physics::EditorWorldBus::Handler
, private AzToolsFramework::EditorEntityContextNotificationBus::Handler
, private AzToolsFramework::EditorEvents::Bus::Handler
{
public:
AZ_COMPONENT(EditorSystemComponent, "{560F08DC-94F5-4D29-9AD4-CDFB3B57C654}");
@@ -60,6 +61,10 @@ namespace PhysX
void OnStartPlayInEditorBegin() override;
void OnStopPlayInEditor() override;
// AztoolsFramework::EditorEvents::Bus::Handler
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override;
void NotifyRegisterViews() override;
AZ::Data::AssetId GenerateSurfaceTypesLibrary();
AzPhysics::SceneHandle m_editorWorldSceneHandle = AzPhysics::InvalidSceneHandle;
@@ -330,10 +330,8 @@ namespace PhysX
}
const bool hasNonUniformScale = (AZ::NonUniformScaleRequestBus::FindFirstHandler(GetEntityId()) != nullptr);
// the value for the subdivision level doesn't matter in the runtime, because any approximation of primitives will already have
// happened in the editor, so can pass an arbitrary value here
AZ::u8 subdivisionLevel = 0;
Utils::GetShapesFromAsset(physicsAssetConfiguration, componentColliderConfiguration, hasNonUniformScale, subdivisionLevel, m_shapes);
Utils::GetShapesFromAsset(physicsAssetConfiguration, componentColliderConfiguration, hasNonUniformScale,
physicsAssetConfiguration.m_subdivisionLevel, m_shapes);
return true;
}
@@ -514,6 +514,8 @@ namespace PhysX
break;
case Physics::ShapeType::PhysicsAsset:
colliderComponent = gameEntity->CreateComponent<MeshColliderComponent>();
m_shapeConfiguration.m_physicsAsset.m_configuration.m_subdivisionLevel = m_shapeConfiguration.m_subdivisionLevel;
colliderComponent->SetShapeConfigurationList({ AZStd::make_pair(sharedColliderConfig,
AZStd::make_shared<Physics::PhysicsAssetShapeConfiguration>(m_shapeConfiguration.m_physicsAsset.m_configuration)) });
@@ -561,6 +563,8 @@ namespace PhysX
void EditorColliderComponent::CreateStaticEditorCollider()
{
m_cachedAabbDirty = true;
// Don't create static rigid body in the editor if current entity components
// don't allow creation of runtime static rigid body component
if (!StaticRigidBodyUtils::CanCreateRuntimeComponent(*GetEntity()))
@@ -1014,11 +1018,17 @@ namespace PhysX
// PhysX::ColliderShapeBus
AZ::Aabb EditorColliderComponent::GetColliderShapeAabb()
{
return PhysX::Utils::GetColliderAabb(GetWorldTM()
, m_hasNonUniformScale
, m_shapeConfiguration.m_subdivisionLevel
, m_shapeConfiguration.GetCurrent()
, m_configuration);
if (m_cachedAabbDirty)
{
m_cachedAabb = PhysX::Utils::GetColliderAabb(GetWorldTM()
, m_hasNonUniformScale
, m_shapeConfiguration.m_subdivisionLevel
, m_shapeConfiguration.GetCurrent()
, m_configuration);
m_cachedAabbDirty = false;
}
return m_cachedAabb;
}
void EditorColliderComponent::UpdateShapeConfigurationScale()
@@ -261,6 +261,8 @@ namespace PhysX
bool m_hasNonUniformScale = false; //!< Whether there is a non-uniform scale component on this entity.
AZ::Vector3 m_cachedNonUniformScale = AZ::Vector3::CreateOne(); //!< Caches the current non-uniform scale.
mutable AZStd::optional<Physics::CookedMeshShapeConfiguration> m_scaledPrimitive; //!< Approximation for non-uniformly scaled primitive.
AZ::Aabb m_cachedAabb = AZ::Aabb::CreateNull(); //!< Cache the Aabb to avoid recalculating it.
bool m_cachedAabbDirty = true; //!< Track whether the cached Aabb needs to be recomputed.
AZ::ComponentDescriptor::StringWarningArray m_componentWarnings;
};
@@ -36,7 +36,7 @@ namespace PhysX
const bool hasNonUniformScaleComponent = (AZ::NonUniformScaleRequestBus::FindFirstHandler(entity->GetId()) != nullptr);
const AZStd::vector<EditorColliderComponent*> colliders = entity->FindComponents<EditorColliderComponent>();
const AZStd::vector<EditorColliderComponent*> colliders = entity->FindComponents<EditorColliderComponent>();
for (const EditorColliderComponent* collider : colliders)
{
const EditorProxyShapeConfig& shapeConfigurationProxy = collider->GetShapeConfiguration();
@@ -45,12 +45,14 @@ namespace PhysX
continue;
}
const Physics::ColliderConfiguration colliderConfiguration = collider->GetColliderConfigurationScaled();
const Physics::ColliderConfiguration colliderConfigurationScaled = collider->GetColliderConfigurationScaled();
const Physics::ColliderConfiguration colliderConfigurationUnscaled = collider->GetColliderConfiguration();
if (shapeConfigurationProxy.IsAssetConfig())
{
AZStd::vector<AZStd::shared_ptr<Physics::Shape>> shapes;
Utils::GetShapesFromAsset(shapeConfigurationProxy.m_physicsAsset.m_configuration,
colliderConfiguration, hasNonUniformScaleComponent, shapeConfigurationProxy.m_subdivisionLevel, shapes);
colliderConfigurationUnscaled, hasNonUniformScaleComponent, shapeConfigurationProxy.m_subdivisionLevel, shapes);
for (const auto& shape : shapes)
{
@@ -64,7 +66,7 @@ namespace PhysX
if (!hasNonUniformScaleComponent)
{
AZStd::shared_ptr<Physics::Shape> shape = AZ::Interface<Physics::System>::Get()->CreateShape(
colliderConfiguration, shapeConfiguration);
colliderConfigurationScaled, shapeConfiguration);
AZ_Assert(shape, "CreateEditorWorldRigidBody: Shape must not be null!");
if (shape)
{
@@ -73,7 +75,6 @@ namespace PhysX
}
else
{
const Physics::ColliderConfiguration colliderConfigurationUnscaled = collider->GetColliderConfiguration();
auto convexConfig = Utils::CreateConvexFromPrimitive(colliderConfigurationUnscaled, shapeConfiguration,
shapeConfigurationProxy.m_subdivisionLevel, shapeConfiguration.m_scale);
auto colliderConfigurationNoOffset = colliderConfigurationUnscaled;
@@ -377,7 +378,7 @@ namespace PhysX
configuration.m_kinematic = m_config.m_kinematic;
configuration.m_colliderAndShapeData = Internal::GetCollisionShapes(GetEntity());
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
{
m_rigidBodyHandle = sceneInterface->AddSimulatedBody(m_editorSceneHandle, &configuration);
m_editorBody = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(m_editorSceneHandle, m_rigidBodyHandle));
@@ -15,38 +15,18 @@
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzFramework/Physics/Utils.h>
#include <AzFramework/Physics/Material.h>
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
#include <AzFramework/Physics/Configuration/RigidBodyConfiguration.h>
#include <AzFramework/Physics/Configuration/StaticRigidBodyConfiguration.h>
#include <AzFramework/Asset/AssetSystemBus.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <PhysX/MeshAsset.h>
#include <PhysX/HeightFieldAsset.h>
#include <Source/RigidBody.h>
#include <Source/RigidBodyStatic.h>
#include <Source/Utils.h>
#include <Source/Collision.h>
#include <Source/Shape.h>
#include <Source/Joint.h>
#include <Source/SphereColliderComponent.h>
#include <Source/BoxColliderComponent.h>
#include <Source/CapsuleColliderComponent.h>
#include <Source/Pipeline/MeshAssetHandler.h>
#include <Source/Pipeline/HeightFieldAssetHandler.h>
#include <Source/PhysXCharacters/API/CharacterUtils.h>
#include <Source/PhysXCharacters/API/CharacterController.h>
#include <Source/WindProvider.h>
#ifdef PHYSX_EDITOR
#include <Source/EditorColliderComponent.h>
#include <Editor/EditorWindow.h>
#include <Editor/PropertyTypes.h>
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
#endif
#include <PhysX/Debug/PhysXDebugInterface.h>
#include <System/PhysXSystem.h>
@@ -233,21 +213,11 @@ namespace PhysX
Physics::CollisionRequestBus::Handler::BusConnect();
Physics::CharacterSystemRequestBus::Handler::BusConnect();
#ifdef PHYSX_EDITOR
PhysX::Editor::RegisterPropertyTypes();
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
#endif
ActivatePhysXSystem();
}
void SystemComponent::Deactivate()
{
#ifdef PHYSX_EDITOR
AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
#endif
AZ::TickBus::Handler::BusDisconnect();
Physics::CharacterSystemRequestBus::Handler::BusDisconnect();
Physics::CollisionRequestBus::Handler::BusDisconnect();
@@ -272,19 +242,6 @@ namespace PhysX
m_assetHandlers.clear(); //this need to be after m_physXSystem->Shutdown(); For it will drop the default material library reference.
}
#ifdef PHYSX_EDITOR
// AztoolsFramework::EditorEvents::Bus::Handler overrides
void SystemComponent::PopulateEditorGlobalContextMenu([[maybe_unused]] QMenu* menu, [[maybe_unused]] const AZ::Vector2& point, [[maybe_unused]] int flags)
{
}
void SystemComponent::NotifyRegisterViews()
{
PhysX::Editor::EditorWindow::RegisterViewClass();
}
#endif
physx::PxConvexMesh* SystemComponent::CreateConvexMesh(const void* vertices, AZ::u32 vertexNum, AZ::u32 vertexStride)
{
physx::PxConvexMeshDesc desc;
@@ -464,54 +421,6 @@ namespace PhysX
}
}
void SystemComponent::AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, [[maybe_unused]] bool addEditorComponents)
{
[[maybe_unused]] Physics::ShapeType shapeType = shapeConfiguration.GetShapeType();
#ifdef PHYSX_EDITOR
if (addEditorComponents)
{
entity->CreateComponent<EditorColliderComponent>(colliderConfiguration, shapeConfiguration);
}
else
#else
{
if (shapeType == Physics::ShapeType::Sphere)
{
const Physics::SphereShapeConfiguration& sphereConfiguration = static_cast<const Physics::SphereShapeConfiguration&>(shapeConfiguration);
auto sphereColliderComponent = entity->CreateComponent<SphereColliderComponent>();
sphereColliderComponent->SetShapeConfigurationList({ AZStd::make_pair(
AZStd::make_shared<Physics::ColliderConfiguration>(colliderConfiguration),
AZStd::make_shared<Physics::SphereShapeConfiguration>(sphereConfiguration)) });
}
else if (shapeType == Physics::ShapeType::Box)
{
const Physics::BoxShapeConfiguration& boxConfiguration = static_cast<const Physics::BoxShapeConfiguration&>(shapeConfiguration);
auto boxColliderComponent = entity->CreateComponent<BoxColliderComponent>();
boxColliderComponent->SetShapeConfigurationList({ AZStd::make_pair(
AZStd::make_shared<Physics::ColliderConfiguration>(colliderConfiguration),
AZStd::make_shared<Physics::BoxShapeConfiguration>(boxConfiguration)) });
}
else if (shapeType == Physics::ShapeType::Capsule)
{
const Physics::CapsuleShapeConfiguration& capsuleConfiguration = static_cast<const Physics::CapsuleShapeConfiguration&>(shapeConfiguration);
auto capsuleColliderComponent = entity->CreateComponent<CapsuleColliderComponent>();
capsuleColliderComponent->SetShapeConfigurationList({ AZStd::make_pair(
AZStd::make_shared<Physics::ColliderConfiguration>(colliderConfiguration),
AZStd::make_shared<Physics::CapsuleShapeConfiguration>(capsuleConfiguration)) });
}
}
AZ_Error("PhysX System", !addEditorComponents, "AddColliderComponentToEntity(): Trying to add an Editor collider component in a stand alone build.",
static_cast<AZ::u8>(shapeType));
#endif
{
AZ_Error("PhysX System", shapeType == Physics::ShapeType::Sphere || shapeType == Physics::ShapeType::Box || shapeType == Physics::ShapeType::Capsule,
"AddColliderComponentToEntity(): Using Shape of type %d is not implemented.", static_cast<AZ::u8>(shapeType));
}
}
// Physics::CharacterSystemRequestBus
AZStd::unique_ptr<Physics::Character> SystemComponent::CreateCharacter(const Physics::CharacterConfiguration&
characterConfig, const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle)
-16
View File
@@ -36,9 +36,6 @@
#include <DefaultWorldComponent.h>
#include <Material.h>
#ifdef PHYSX_EDITOR
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#endif
namespace AzPhysics
{
struct StaticRigidBodyConfiguration;
@@ -61,10 +58,6 @@ namespace PhysX
, public Physics::SystemRequestBus::Handler
, public PhysX::SystemRequestsBus::Handler
, public Physics::CharacterSystemRequestBus::Handler
#ifdef PHYSX_EDITOR
, public AzToolsFramework::EditorEntityContextNotificationBus::Handler
, private AzToolsFramework::EditorEvents::Bus::Handler
#endif
, private Physics::CollisionRequestBus::Handler
, private AZ::TickBus::Handler
{
@@ -100,8 +93,6 @@ namespace PhysX
bool CookTriangleMeshToMemory(const AZ::Vector3* vertices, AZ::u32 vertexCount,
const AZ::u32* indices, AZ::u32 indexCount, AZStd::vector<AZ::u8>& result) override;
void AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, bool addEditorComponents = false) override;
physx::PxFilterData CreateFilterData(const AzPhysics::CollisionLayer& layer, const AzPhysics::CollisionGroup& group) override;
physx::PxCooking* GetCooking() override;
@@ -125,13 +116,6 @@ namespace PhysX
void Activate() override;
void Deactivate() override;
#ifdef PHYSX_EDITOR
// AztoolsFramework::EditorEvents::Bus::Handler overrides
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override;
void NotifyRegisterViews() override;
#endif
// Physics::SystemRequestBus::Handler
AZStd::shared_ptr<Physics::Shape> CreateShape(const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& configuration) override;
AZStd::shared_ptr<Physics::Material> CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) override;
@@ -24,6 +24,8 @@
#include <AzFramework/Components/TransformComponent.h>
#include <PhysX/ComponentTypeIds.h>
#include <PhysX/SystemComponentBus.h>
#include <Source/SphereColliderComponent.h>
#include <Source/CapsuleColliderComponent.h>
#include <System/PhysXSystem.h>
#include <Tests/PhysXTestFixtures.h>
#include <Tests/PhysXTestUtil.h>
@@ -31,6 +33,51 @@
namespace PhysX
{
namespace Internal
{
void AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration)
{
Physics::ShapeType shapeType = shapeConfiguration.GetShapeType();
switch (shapeType)
{
case Physics::ShapeType::Sphere:
{
const Physics::SphereShapeConfiguration& sphereConfiguration = static_cast<const Physics::SphereShapeConfiguration&>(shapeConfiguration);
auto sphereColliderComponent = entity->CreateComponent<SphereColliderComponent>();
sphereColliderComponent->SetShapeConfigurationList({ AZStd::make_pair(
AZStd::make_shared<Physics::ColliderConfiguration>(colliderConfiguration),
AZStd::make_shared<Physics::SphereShapeConfiguration>(sphereConfiguration)) });
}
break;
case Physics::ShapeType::Box:
{
const Physics::BoxShapeConfiguration& boxConfiguration = static_cast<const Physics::BoxShapeConfiguration&>(shapeConfiguration);
auto boxColliderComponent = entity->CreateComponent<BoxColliderComponent>();
boxColliderComponent->SetShapeConfigurationList({ AZStd::make_pair(
AZStd::make_shared<Physics::ColliderConfiguration>(colliderConfiguration),
AZStd::make_shared<Physics::BoxShapeConfiguration>(boxConfiguration)) });
}
break;
case Physics::ShapeType::Capsule:
{
const Physics::CapsuleShapeConfiguration& capsuleConfiguration = static_cast<const Physics::CapsuleShapeConfiguration&>(shapeConfiguration);
auto capsuleColliderComponent = entity->CreateComponent<CapsuleColliderComponent>();
capsuleColliderComponent->SetShapeConfigurationList({ AZStd::make_pair(
AZStd::make_shared<Physics::ColliderConfiguration>(colliderConfiguration),
AZStd::make_shared<Physics::CapsuleShapeConfiguration>(capsuleConfiguration)) });
}
break;
default:
{
AZ_Error("PhysX", false,
"AddColliderComponentToEntity(): Using Shape of type %d is not implemented.", static_cast<AZ::u8>(shapeType));
}
break;
}
}
}
// transform for a floor centred at x = 0, y = 0, with top at level z = 0
static const AZ::Transform DefaultFloorTransform = AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisZ(-0.5f));
@@ -367,8 +414,7 @@ namespace PhysX
auto triggerEntity = AZStd::make_unique<AZ::Entity>("TriggerEntity");
triggerEntity->CreateComponent<AzFramework::TransformComponent>()->SetWorldTM(AZ::Transform::Identity());
triggerEntity->CreateComponent(PhysX::StaticRigidBodyComponentTypeId);
Physics::SystemRequestBus::Broadcast(&Physics::SystemRequests::AddColliderComponentToEntity,
triggerEntity.get(), triggerConfig, boxConfig, false);
Internal::AddColliderComponentToEntity(triggerEntity.get(), triggerConfig, boxConfig);
triggerEntity->Init();
triggerEntity->Activate();
@@ -11,6 +11,4 @@
set(FILES
Source/Module.cpp
Source/SystemComponent.cpp
Source/SystemComponent.h
)
@@ -11,8 +11,6 @@
set(FILES
Source/Module.cpp
Source/SystemComponent.cpp
Source/SystemComponent.h
Tests/PhysXTestCommon.cpp
Tests/PhysXTestCommon.h
Tests/ColliderScalingTests.cpp
+2
View File
@@ -12,6 +12,8 @@
set(FILES
Source/PhysX_precompiled.cpp
Source/PhysX_precompiled.h
Source/SystemComponent.cpp
Source/SystemComponent.h
Include/PhysX/SystemComponentBus.h
Include/PhysX/ColliderComponentBus.h
Include/PhysX/NativeTypeIdentifiers.h
-2
View File
@@ -11,8 +11,6 @@
set(FILES
Source/Module.cpp
Source/SystemComponent.cpp
Source/SystemComponent.h
Source/ComponentDescriptors.cpp
Source/ComponentDescriptors.h
)
-2
View File
@@ -10,8 +10,6 @@
#
set(FILES
Source/SystemComponent.cpp
Source/SystemComponent.h
Source/ComponentDescriptors.cpp
Source/ComponentDescriptors.h
Tests/PhysXComponentBusTests.cpp
@@ -11,4 +11,5 @@
set(GEM_DEPENDENCIES
Gem::Atom_RHI_Metal.Private
Gem::Atom_RHI_Null.Private
)
@@ -14,4 +14,5 @@ set(GEM_DEPENDENCIES
Gem::Atom_RHI_Metal.Builders
Gem::Atom_RHI_Vulkan.Builders
Gem::Atom_RHI_DX12.Builders
Gem::Atom_RHI_Null.Builders
)
@@ -12,4 +12,5 @@
set(GEM_DEPENDENCIES
Gem::Atom_RHI_Vulkan.Private
Gem::Atom_RHI_DX12.Private
Gem::Atom_RHI_Null.Private
)
@@ -14,4 +14,6 @@ set(GEM_DEPENDENCIES
Gem::Atom_RHI_Vulkan.Builders
Gem::Atom_RHI_DX12.Private
Gem::Atom_RHI_DX12.Builders
Gem::Atom_RHI_Null.Private
Gem::Atom_RHI_Null.Builders
)