Merge branch 'stabilization/2106' of https://github.com/aws-lumberyard/o3de into jckand/FoundationAutoStabilization

This commit is contained in:
jckand-amzn
2021-06-17 10:02:05 -05:00
107 changed files with 525 additions and 2995 deletions
@@ -13,13 +13,6 @@ add_subdirectory(asset_processor_tests)
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
## AP Python Tests ##
ly_add_pytest(
NAME AssetPipelineTests.AuxiliaryContent
PATH ${CMAKE_CURRENT_LIST_DIR}/auxiliary_content_tests/auxiliary_content_tests.py
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
TEST_SUITE periodic
)
ly_add_pytest(
NAME AssetPipelineTests.BankInfoParser
PATH ${CMAKE_CURRENT_LIST_DIR}/wwise_bank_dependency_tests/bank_info_parser_tests.py
@@ -1,10 +0,0 @@
#
# 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.
#
@@ -1,96 +0,0 @@
"""
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.
"""
import pytest
import ly_test_tools
import os
import sys
import shutil
import subprocess
import glob
from ly_test_tools.builtin.helpers import *
from ly_test_tools.environment.process_utils import *
from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP
logger = logging.getLogger(__name__)
project_list = ['AutomatedTesting']
@pytest.mark.system
@pytest.mark.SUITE_periodic
class TestAuxiliaryContent:
@pytest.fixture(autouse=True)
def setup_teardown(self, request, workspace, project):
path_to_dev = workspace.paths.engine_root()
os.chdir(path_to_dev)
auxiliaryContentDirName = str.lower(project) + f"_{ASSET_PROCESSOR_PLATFORM_MAP[workspace.asset_processor_platform]}_paks"
self.auxiliaryContentPath = os.path.join(path_to_dev, auxiliaryContentDirName)
def teardown():
if (os.path.exists(self.auxiliaryContentPath)):
shutil.rmtree(self.auxiliaryContentPath)
request.addfinalizer(teardown)
@staticmethod
def scanForLevelPak(path_toscan):
files = glob.glob('{0}/**/level.pak'.format(path_toscan), recursive=True)
return len(files)
@pytest.mark.parametrize('level', ['alldependencies'])
@pytest.mark.parametrize('project', project_list)
def test_CreateAuxiliaryContent_DontSkipLevelPaks(self, workspace, level):
"""
This test ensure that Auxiliary Content contain level.pak files
Test Steps:
1. Run auxiliary content against project under test
2. Validate auxiliary content exists
3. Verifies that level.pak exists
"""
path_to_dev = workspace.paths.engine_root()
bin_path = workspace.paths.build_directory()
auxiliaryContentScriptPath = os.path.join(path_to_dev, 'BuildReleaseAuxiliaryContent.py')
subprocess.check_call(['python', auxiliaryContentScriptPath,
"--buildFolder={0}".format(bin_path),
"--platforms=pc",
f"--project-path={workspace.project}"])
assert os.path.exists(self.auxiliaryContentPath)
assert not self.scanForLevelPak(self.auxiliaryContentPath) == 0
@pytest.mark.parametrize('level', ['alldependencies'])
@pytest.mark.parametrize('project', project_list)
def test_CreateAuxiliaryContent_SkipLevelPaks(self, workspace, level):
"""
This test ensure that Auxiliary Content contain no level.pak file
Test Steps:
1. Run auxiliary content against project under test with skiplevelPaks flag
2. Validate auxiliary content exists
3. Validate level.pak was added to auxiliary content
"""
path_to_dev = workspace.paths.engine_root()
bin_path = workspace.paths.build_directory()
auxiliaryContentScriptPath = os.path.join(path_to_dev, 'BuildReleaseAuxiliaryContent.py')
subprocess.check_call(['python', auxiliaryContentScriptPath,
"--buildFolder={0}".format(bin_path),
"--platforms=pc",
"--skiplevelPaks",
f"--project-path={workspace.project}"])
assert os.path.exists(self.auxiliaryContentPath)
assert self.scanForLevelPak(self.auxiliaryContentPath) == 0
+1 -8
View File
@@ -4060,17 +4060,10 @@ void CCryEditApp::SetEditorWindowTitle(QString sTitleStr, QString sPreTitleStr,
{
if (MainWindow::instance() || m_pConsoleDialog)
{
QString platform = "";
#ifdef WIN64
platform = "[x64]";
#else
platform = "[x86]";
#endif //WIN64
if (sTitleStr.isEmpty())
{
sTitleStr = QObject::tr("Open 3D Engine Editor Beta %1 - Build %2").arg(platform).arg(LY_BUILD);
sTitleStr = QObject::tr("O3DE Editor [Developer Preview]");
}
if (!sPreTitleStr.isEmpty())
@@ -47,8 +47,6 @@ CEditorPreferencesPage_AWS::CEditorPreferencesPage_AWS()
{
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
InitializeSettings();
// TODO Update with AWS svg.
m_icon = QIcon(":/res/AWS_preferences_icon.svg");
}
@@ -77,6 +77,7 @@ namespace O3DE::ProjectManager
return ProjectManagerScreen::CreateProject;
}
// Called when pressing "Create New Project"
void CreateProjectCtrl::NotifyCurrentScreen()
{
ScreenWidget* currentScreen = reinterpret_cast<ScreenWidget*>(m_stack->currentWidget());
@@ -84,6 +85,11 @@ namespace O3DE::ProjectManager
{
currentScreen->NotifyCurrentScreen();
}
// Gather the gems from the project template. When we will have multiple project templates, we need to re-gather them
// on changing the template and let the user know that any further changes on top of the template will be lost.
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
m_gemCatalogScreen->ReinitForProject(projectTemplatePath + "/Template", /*isNewProject=*/true);
}
void CreateProjectCtrl::HandleBackButton()
@@ -151,9 +157,6 @@ namespace O3DE::ProjectManager
{
m_stack->setCurrentIndex(m_stack->currentIndex() + 1);
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
m_gemCatalogScreen->ReinitForProject(projectTemplatePath + "/Template", /*isNewProject=*/true);
Update();
}
else
@@ -89,17 +89,18 @@ namespace O3DE::ProjectManager
return ProjectManagerScreen::UpdateProject;
}
// Called when pressing "Edit Project Settings..."
void UpdateProjectCtrl::NotifyCurrentScreen()
{
m_stack->setCurrentIndex(ScreenOrder::Settings);
Update();
// Gather the available gems that will be shown in the gem catalog.
m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/false);
}
void UpdateProjectCtrl::HandleGemsButton()
{
// The next page is the gem catalog. Gather the available gems that will be shown in the gem catalog.
m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/false);
m_stack->setCurrentWidget(m_gemCatalogScreen);
Update();
}
@@ -43,7 +43,7 @@ namespace AWSCore
bool UseAWSCredentials()
{
return false;
return true;
}
//! Request body for the service API request.
@@ -25,20 +25,24 @@
#include <AzCore/Module/ModuleManagerBus.h>
#include <ResourceMapping/AWSResourceMappingUtils.h>
#include <QSysInfo>
#include <QString>
namespace AWSCore
{
static constexpr const char* EngineVersionJsonKey = "O3DEVersion";
constexpr const char* EngineVersionJsonKey = "O3DEVersion";
constexpr char EditorAWSPreferencesFileName[] = "editor_aws_preferences.setreg";
constexpr char AWSAttributionSettingsPrefixKey[] = "/Amazon/AWS/Preferences";
constexpr char AWSAttributionEnabledKey[] = "/Amazon/AWS/Preferences/AWSAttributionEnabled";
constexpr char AWSAttributionDelaySecondsKey[] = "/Amazon/AWS/Preferences/AWSAttributionDelaySeconds";
constexpr char AWSAttributionLastTimeStampKey[] = "/Amazon/AWS/Preferences/AWSAttributionLastTimeStamp";
constexpr char AWSAttributionApiId[] = "xbzx78kvbk";
constexpr char AWSAttributionApiId[] = "2zxvvmv8d7";
constexpr char AWSAttributionChinaApiId[] = "";
constexpr char AWSAttributionApiStage[] = "prod";
const int AWSAttributionDefaultDelayInDays = 7;
AWSAttributionManager::AWSAttributionManager()
{
@@ -58,12 +62,11 @@ namespace AWSCore
{
if (ShouldGenerateMetric())
{
// 1. Gather metadata and assemble metric
// Gather metadata and assemble metric
AttributionMetric metric;
UpdateMetric(metric);
// 2. Identify region and chose attribution endpoint
// 3. Post metric
// Post metric
SubmitMetric(metric);
}
}
@@ -104,8 +107,7 @@ namespace AWSCore
AZ::u64 delayInSeconds = 0;
if (!m_settingsRegistry->Get(delayInSeconds, AWSAttributionDelaySecondsKey))
{
AZ_Warning("AWSAttributionManager", false, "AWSAttribution delay key not found. Defaulting to delay to day");
delayInSeconds = 86400;
delayInSeconds = 86400 * AWSAttributionDefaultDelayInDays;
m_settingsRegistry->Set(AWSAttributionDelaySecondsKey, delayInSeconds);
}
@@ -243,7 +245,8 @@ namespace AWSCore
metric.SetO3DEVersion(engineVersion);
AZStd::string platform = this->GetPlatform();
metric.SetPlatform(platform, "");
QString productName = QSysInfo::prettyProductName();
metric.SetPlatform(platform, productName.toStdString().c_str());
AZStd::vector<AZStd::string> gemNames;
GetActiveAWSGems(gemNames);
@@ -256,6 +259,7 @@ namespace AWSCore
void AWSAttributionManager::SubmitMetric(AttributionMetric& metric)
{
AWSCore::ServiceAPI::AWSAttributionRequestJob::Config* config = ServiceAPI::AWSAttributionRequestJob::GetDefaultConfig();
// Identify region and chose attribution endpoint
SetApiEndpointAndRegion(config);
ServiceAPI::AWSAttributionRequestJob* requestJob = ServiceAPI::AWSAttributionRequestJob::Create(
@@ -266,7 +270,12 @@ namespace AWSCore
UpdateLastSend();
AZ_Printf("AWSAttributionManager", "AWSAttribution metric submit success");
}, {}, config);
},
[this](ServiceAPI::AWSAttributionRequestJob* failJob)
{
AZ_Error("AWSAttributionManager", false, "Metrics send error: %s", failJob->error.message.c_str());
},
config);
requestJob->parameters.metric = metric;
requestJob->Start();
@@ -19,14 +19,16 @@
namespace AWSCore
{
constexpr char AWSAttributionMetricDefaultO3DEVersion[] = "1.1";
AttributionMetric::AttributionMetric(const AZStd::string& timestamp)
: m_version("1.1")
: m_version(AWSAttributionMetricDefaultO3DEVersion)
, m_timestamp(timestamp)
{
}
AttributionMetric::AttributionMetric()
: m_version("1.1")
: m_version(AWSAttributionMetricDefaultO3DEVersion)
{
m_timestamp = AttributionMetric::GenerateTimeStamp();
}
@@ -32,6 +32,8 @@
#include <AzCore/Module/ModuleManagerBus.h>
#include <TestFramework/AWSCoreFixture.h>
#include <QSysInfo>
#include <QString>
using namespace AWSCore;
@@ -405,6 +407,7 @@ namespace AWSAttributionUnitTest
AZStd::string serializedMetricValue = metric.SerializeToJson();
ASSERT_TRUE(serializedMetricValue.find("\"o3de_version\":\"1.0.0.0\"") != AZStd::string::npos);
ASSERT_TRUE(serializedMetricValue.find(AZ::GetPlatformName(AZ::g_currentPlatform)) != AZStd::string::npos);
ASSERT_TRUE(serializedMetricValue.find(QSysInfo::prettyProductName().toStdString().c_str()) != AZStd::string::npos);
ASSERT_TRUE(serializedMetricValue.find("AWSCore.Editor") != AZStd::string::npos);
ASSERT_TRUE(serializedMetricValue.find("AWSClientAuth") != AZStd::string::npos);
@@ -25,8 +25,6 @@ AlphaSource_Packed = 0
AlphaSource_Split = 1
AlphaSource_None = 2
ForwardPassIndex = 1
function ConfigureAlphaBlending(shaderItem)
shaderItem:GetRenderStatesOverride():SetDepthEnabled(true)
shaderItem:GetRenderStatesOverride():SetDepthWriteMask(DepthWriteMask_Zero)
@@ -58,15 +56,17 @@ end
function Process(context)
local opacityMode = context:GetMaterialPropertyValue_enum("opacity.mode")
local forwardPassEDS = context:GetShaderByTag("ForwardPass_EDS")
if(opacityMode == OpacityMode_Blended) then
ConfigureAlphaBlending(context:GetShader(ForwardPassIndex))
context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent")
ConfigureAlphaBlending(forwardPassEDS)
forwardPassEDS:SetDrawListTagOverride("transparent")
elseif(opacityMode == OpacityMode_TintedTransparent) then
ConfigureDualSourceBlending(context:GetShader(ForwardPassIndex))
context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent")
ConfigureDualSourceBlending(forwardPassEDS)
forwardPassEDS:SetDrawListTagOverride("transparent")
else
ResetAlphaBlending(context:GetShader(ForwardPassIndex))
context:GetShader(ForwardPassIndex):SetDrawListTagOverride("") -- reset to default draw list
ResetAlphaBlending(forwardPassEDS)
forwardPassEDS:SetDrawListTagOverride("") -- reset to default draw list
end
end
@@ -74,7 +74,9 @@ function Process(context)
shadowMapWithPS:SetEnabled(opacityMode == OpacityMode_Cutout)
forwardPass:SetEnabled(opacityMode == OpacityMode_Cutout)
TrySetShaderEnabled(lowEndForwardEDS, (opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent))
-- Only enable lowEndForwardEDS in Opaque mode, Transparent mode will be handled by forwardPassEDS. The transparent pass uses the "transparent" draw tag
-- for both standard and low end pipelines, so this keeps both shaders from rendering to the transparent draw list.
TrySetShaderEnabled(lowEndForwardEDS, opacityMode == OpacityMode_Opaque)
TrySetShaderEnabled(lowEndForward, opacityMode == OpacityMode_Cutout)
end
@@ -226,7 +226,7 @@ float ProjectedShadow::GetVisibilityEsm()
}
const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize;
const Texture2DArray<float> expShadowmap = PassSrg::m_projectedExponentialShadowmap;
const Texture2DArray<float> shadowmap = PassSrg::m_projectedExponentialShadowmap;
if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin &&
m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin)
@@ -243,10 +243,12 @@ float ProjectedShadow::GetVisibilityEsm()
const float depth = PerspectiveDepthToLinear(
m_shadowPosition.z,
coefficients);
const float expDepthInShadowmap = expShadowmap.Sample(
const float occluder = shadowmap.Sample(
PassSrg::LinearSampler,
float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r;
const float ratio = exp(-EsmExponentialShift * depth) * expDepthInShadowmap;
const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder);
const float ratio = exp(exponent);
// pow() mitigates light bleeding to shadows from near shadow casters.
return saturate( pow(ratio, 8) );
}
@@ -265,7 +267,7 @@ float ProjectedShadow::GetVisibilityEsmPcf()
}
const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize;
const Texture2DArray<float> expShadowmap = PassSrg::m_projectedExponentialShadowmap;
const Texture2DArray<float> shadowmap = PassSrg::m_projectedExponentialShadowmap;
if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin &&
m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin)
@@ -282,10 +284,12 @@ float ProjectedShadow::GetVisibilityEsmPcf()
const float depth = PerspectiveDepthToLinear(
m_shadowPosition.z,
coefficients);
const float expDepthInShadowmap = expShadowmap.Sample(
const float occluder = shadowmap.Sample(
PassSrg::LinearSampler,
float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r;
float ratio = exp(-EsmExponentialShift * depth) * expDepthInShadowmap;
const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder);
float ratio = exp(exponent);
static const float pcfFallbackThreshold = 1.04;
if (ratio > pcfFallbackThreshold)
@@ -92,6 +92,8 @@ partial ShaderResourceGroup ViewSrg
uint m_filteringSampleCount;
float2 m_unprojectConstants;
float m_bias;
float m_esmExponent;
float3 m_padding;
};
StructuredBuffer<ProjectedShadow> m_projectedShadows;
@@ -56,7 +56,6 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
return; // Early return if filter is disabled.
}
float depth = 0.;
switch (o_shadowmapLightType)
{
case ShadowmapLightType::Directional:
@@ -68,9 +67,15 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
// and it often causes light bleeding with ESM.
// So this converts it to "depth" to emphasize the difference
// within the frustum.
depth = (depthInClip - distanceMin) / (1. - distanceMin);
}
const float depth = (depthInClip - distanceMin) / (1. - distanceMin);
// Todo: Expose Esm exponent slider for directional lights
// This would remove the exp calculation below, collapsing it into a subtraction in DirectionalLightShadow.azsli
// ATOM-15775
const float outValue = exp(EsmExponentialShift * depth);
PassSrg::m_outputShadowmap[dispatchId].r = outValue;
break;
}
case ShadowmapLightType::Spot:
{
const float3 coefficients = float3(
@@ -84,12 +89,9 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
// and it often causes light bleeding with ESM.
// So this converts it to a linear depth to emphasize the
// difference like a orthogonal depth.
depth = PerspectiveDepthToLinear(depthInClip, coefficients);
}
PassSrg::m_outputShadowmap[dispatchId].r = PerspectiveDepthToLinear(depthInClip, coefficients);
break;
}
}
const float outValue = exp(EsmExponentialShift * depth);
PassSrg::m_outputShadowmap[dispatchId].r = outValue;
}
@@ -100,10 +100,13 @@ namespace AZ
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
//! Sets the shadowmap Pcf (percentage closer filtering) method.
virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0;
//! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow.
virtual void SetEsmExponent(LightHandle handle, float exponent) = 0;
//! Sets all of the the disk data for the provided LightHandle.
virtual void SetDiskData(LightHandle handle, const DiskLightData& data) = 0;
};
} // namespace Render
} // namespace AZ
@@ -82,6 +82,8 @@ namespace AZ
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
//! Sets the shadowmap Pcf (percentage closer filtering) method.
virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0;
//! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow.
virtual void SetEsmExponent(LightHandle handle, float exponent) = 0;
//! Sets all of the the point data for the provided LightHandle.
virtual void SetPointData(LightHandle handle, const PointLightData& data) = 0;
};
@@ -343,6 +343,11 @@ namespace AZ
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method);
}
void DiskLightFeatureProcessor::SetEsmExponent(LightHandle handle, float exponent)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, exponent);
}
void DiskLightFeatureProcessor::UpdateShadow(LightHandle handle)
{
const DiskLightData& diskLight = m_diskLightData.GetData(handle.GetIndex());
@@ -60,6 +60,7 @@ namespace AZ
void SetPredictionSampleCount(LightHandle handle, uint16_t count) override;
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
void SetPcfMethod(LightHandle handle, PcfMethod method) override;
void SetEsmExponent(LightHandle handle, float esmExponent) override;
void SetDiskData(LightHandle handle, const DiskLightData& data) override;
@@ -192,9 +192,7 @@ namespace AZ
OnShaderReloaded();
}
void LightCullingTilePreparePass::OnShaderVariantReinitialized(
const AZ::RPI::Shader&, const AZ::RPI::ShaderVariantId&,
AZ::RPI::ShaderVariantStableId)
void LightCullingTilePreparePass::OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant&)
{
OnShaderReloaded();
}
@@ -56,7 +56,7 @@ namespace AZ
// ShaderReloadNotificationBus overrides...
void OnShaderReinitialized(const AZ::RPI::Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<AZ::RPI::ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const AZ::RPI::Shader& shader, const AZ::RPI::ShaderVariantId& shaderVariantId, AZ::RPI::ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant& shaderVariant) override;
// Scope producer functions...
void CompileResources(const RHI::FrameGraphCompileContext& context) override;
@@ -312,5 +312,10 @@ namespace AZ
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method);
}
void PointLightFeatureProcessor::SetEsmExponent(LightHandle handle, float esmExponent)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, esmExponent);
}
} // namespace Render
} // namespace AZ
@@ -57,6 +57,7 @@ namespace AZ
void SetPredictionSampleCount(LightHandle handle, uint16_t count) override;
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
void SetPcfMethod(LightHandle handle, PcfMethod method) override;
void SetEsmExponent(LightHandle handle, float esmExponent) override;
void SetPointData(LightHandle handle, const PointLightData& data) override;
const Data::Instance<RPI::Buffer> GetLightBuffer() const;
@@ -199,7 +199,7 @@ namespace AZ
}
}
void MorphTargetDispatchItem::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset<AZ::RPI::ShaderAsset>& shaderAsset)
void MorphTargetDispatchItem::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset<RPI::ShaderAsset>& shaderAsset)
{
if (!Init())
{
@@ -207,7 +207,7 @@ namespace AZ
}
}
void MorphTargetDispatchItem::OnShaderVariantReinitialized([[maybe_unused]] const RPI::Shader& shader, [[maybe_unused]] const RPI::ShaderVariantId& shaderVariantId, [[maybe_unused]] RPI::ShaderVariantStableId shaderVariantStableId)
void MorphTargetDispatchItem::OnShaderVariantReinitialized(const RPI::ShaderVariant&)
{
if (!Init())
{
@@ -72,8 +72,8 @@ namespace AZ
// ShaderInstanceNotificationBus::Handler overrides
void OnShaderReinitialized(const RPI::Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<AZ::RPI::ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override;
void OnShaderAssetReinitialized(const Data::Asset<RPI::ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override;
RHI::DispatchItem m_dispatchItem;
@@ -458,9 +458,13 @@ namespace AZ
bool ProfilingCaptureSystemComponent::CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath)
{
// Start the cpu profiling
RHI::CpuProfiler::Get()->SetProfilerEnabled(true);
bool wasEnabled = RHI::CpuProfiler::Get()->IsProfilerEnabled();
if (!wasEnabled)
{
RHI::CpuProfiler::Get()->SetProfilerEnabled(true);
}
const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath]()
const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath, wasEnabled]()
{
JsonSerializerSettings serializationSettings;
serializationSettings.m_keepDefaults = true;
@@ -481,14 +485,22 @@ namespace AZ
saveResult.GetError().c_str());
AZ_Warning("ProfilingCaptureSystemComponent", false, captureInfo.c_str());
}
else
{
AZ_Printf("ProfilingCaptureSystemComponent", "Cpu profiling statistics was saved to file [%s]\n", outputFilePath.c_str());
}
// Disable the profiler again
RHI::CpuProfiler::Get()->SetProfilerEnabled(false);
if (!wasEnabled)
{
RHI::CpuProfiler::Get()->SetProfilerEnabled(false);
}
// Notify listeners that the pass' PipelineStatistics queries capture has finished.
ProfilingCaptureNotificationBus::Broadcast(&ProfilingCaptureNotificationBus::Events::OnCaptureCpuProfilingStatisticsFinished,
saveResult.IsSuccess(),
captureInfo);
});
// Start the TickBus.
@@ -354,9 +354,9 @@ namespace AZ
Init();
}
void RayTracingPass::OnShaderVariantReinitialized([[maybe_unused]] const RPI::Shader& shader, [[maybe_unused]] const RPI::ShaderVariantId& shaderVariantId, [[maybe_unused]] RPI::ShaderVariantStableId shaderVariantStableId)
void RayTracingPass::OnShaderVariantReinitialized(const RPI::ShaderVariant&)
{
Init();
}
} // namespace RPI
} // namespace Render
} // namespace AZ
@@ -53,7 +53,7 @@ namespace AZ
// ShaderReloadNotificationBus::Handler overrides
void OnShaderReinitialized(const RPI::Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<RPI::ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override;
// load the raytracing shaders and setup pipeline states
void Init();
@@ -162,12 +162,21 @@ namespace AZ::Render
void ProjectedShadowFeatureProcessor::SetPcfMethod(ShadowId id, PcfMethod method)
{
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetPcfMethod().");
ShadowData& shadowData = m_shadowData.GetElement<ShadowDataIndex>(id.GetIndex());
shadowData.m_pcfMethod = method;
m_deviceBufferNeedsUpdate = true;
}
void ProjectedShadowFeatureProcessor::SetEsmExponent(ShadowId id, float exponent)
{
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetEsmExponent().");
ShadowData& shadowData = m_shadowData.GetElement<ShadowDataIndex>(id.GetIndex());
shadowData.m_esmExponent = exponent;
m_deviceBufferNeedsUpdate = true;
}
void ProjectedShadowFeatureProcessor::SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method)
{
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowFilterMethod().");
@@ -52,6 +52,7 @@ namespace AZ::Render
void SetFieldOfViewY(ShadowId id, float fieldOfViewYRadians) override;
void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) override;
void SetPcfMethod(ShadowId id, PcfMethod method);
void SetEsmExponent(ShadowId id, float exponent);
void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) override;
void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) override;
void SetPredictionSampleCount(ShadowId id, uint16_t count) override;
@@ -73,6 +74,8 @@ namespace AZ::Render
uint32_t m_filteringSampleCount = 0;
AZStd::array<float, 2> m_unprojectConstants = { {0, 0} };
float m_bias;
float m_esmExponent = 87.0f;
float m_padding[3];
};
// CPU data used for constructing & updating ShadowData
@@ -65,9 +65,13 @@ namespace AZ
}
}
void SkinnedMeshComputePass::OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId&, RPI::ShaderVariantStableId)
void SkinnedMeshComputePass::OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant)
{
OnShaderReinitialized(shader);
ComputePass::OnShaderVariantReinitialized(shaderVariant);
if (m_skinnedMeshFeatureProcessor)
{
m_skinnedMeshFeatureProcessor->OnSkinningShaderReinitialized(m_shader);
}
}
} // namespace Render
} // namespace AZ
@@ -44,7 +44,7 @@ namespace AZ
// ShaderReloadNotificationBus::Handler overrides...
void OnShaderReinitialized(const RPI::Shader& shader) override;
void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override;
SkinnedMeshFeatureProcessor* m_skinnedMeshFeatureProcessor = nullptr;
};
@@ -12,6 +12,7 @@
#pragma once
#include <AzCore/Debug/EventTrace.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/string/string.h>
@@ -87,6 +88,8 @@ namespace AZ
//! Enable/Disable the CpuProfiler
virtual void SetProfilerEnabled(bool enabled) = 0;
virtual bool IsProfilerEnabled() const = 0 ;
};
} // namespace RPI
@@ -102,6 +102,7 @@ namespace AZ
void EndTimeRegion() final;
void FlushTimeRegionMap(TimeRegionMap& timeRegionMap) final;
void SetProfilerEnabled(bool enabled) final;
bool IsProfilerEnabled() const final;
private:
// Lazily create and register the local thread data
@@ -11,6 +11,7 @@
*/
#pragma once
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/FreeListAllocator.h>
#include <Atom/RHI/PoolAllocator.h>
#include <Atom/RHI/MemoryAllocation.h>
@@ -160,6 +161,7 @@ namespace AZ
template <class Traits>
void MemorySubAllocator<Traits>::GarbageCollect()
{
AZ_ATOM_PROFILE_FUNCTION("RHI", "MemorySubAllocator: GarbageCollect");
for (PageContext& pageContext : m_pageContexts)
{
pageContext.m_allocator.GarbageCollect();
@@ -11,6 +11,7 @@
*/
#pragma once
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/Object.h>
#include <AzCore/std/parallel/mutex.h>
#include <AzCore/std/containers/vector.h>
@@ -169,6 +170,7 @@ namespace AZ
template <typename Traits>
void ObjectCollector<Traits>::Collect(bool forceFlush)
{
AZ_ATOM_PROFILE_FUNCTION("DX12", "ObjectCollector: Collect");
m_mutex.lock();
if (m_pendingObjects.size())
{
@@ -11,6 +11,7 @@
*/
#include <Atom/RHI/CommandQueue.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/Device.h>
namespace AZ
@@ -86,6 +87,7 @@ namespace AZ
void CommandQueue::FlushCommands()
{
AZ_ATOM_PROFILE_FUNCTION("RHI", "CommandQueue: FlushCommands");
while (!m_isWorkQueueEmpty && !m_isQuitting)
{
AZStd::this_thread::yield();
@@ -186,6 +186,12 @@ namespace AZ
}
}
bool CpuProfilerImpl::IsProfilerEnabled() const
{
return m_enabled;
}
void CpuProfilerImpl::RegisterThreadStorage()
{
AZStd::unique_lock<AZStd::mutex> lock(m_threadRegisterMutex);
+3
View File
@@ -10,6 +10,7 @@
*
*/
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/Device.h>
#include <Atom/RHI/MemoryStatisticsBus.h>
@@ -151,6 +152,7 @@ namespace AZ
{
if (ValidateIsInitialized() && ValidateIsInFrame())
{
AZ_ATOM_PROFILE_FUNCTION("RHI", "Device: EndFrame");
EndFrameInternal();
m_isInFrame = false;
return ResultCode::Success;
@@ -172,6 +174,7 @@ namespace AZ
{
if (ValidateIsInitialized() && ValidateIsNotInFrame())
{
AZ_ATOM_PROFILE_FUNCTION("RHI", "Device: CompileMemoryStatistics");
MemoryStatisticsBuilder builder;
builder.Begin(memoryStatistics, reportFlags);
CompileMemoryStatisticsInternal(builder);
+9 -7
View File
@@ -9,18 +9,19 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/RHI/FrameGraph.h>
#include <Atom/RHI/SwapChainFrameAttachment.h>
#include <Atom/RHI/BufferFrameAttachment.h>
#include <Atom/RHI/ImageFrameAttachment.h>
#include <Atom/RHI/BufferScopeAttachment.h>
#include <Atom/RHI/ImageScopeAttachment.h>
#include <Atom/RHI/ResolveScopeAttachment.h>
#include <Atom/RHI/SwapChain.h>
#include <Atom/RHI/BufferPoolBase.h>
#include <Atom/RHI/BufferScopeAttachment.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/FrameGraph.h>
#include <Atom/RHI/ImageFrameAttachment.h>
#include <Atom/RHI/ImagePoolBase.h>
#include <Atom/RHI/ImageScopeAttachment.h>
#include <Atom/RHI/QueryPool.h>
#include <Atom/RHI/ResolveScopeAttachment.h>
#include <Atom/RHI/Scope.h>
#include <Atom/RHI/SwapChain.h>
#include <Atom/RHI/SwapChainFrameAttachment.h>
#include <AzCore/Debug/EventTrace.h>
#include <AzCore/std/sort.h>
@@ -76,6 +77,7 @@ namespace AZ
void FrameGraph::Clear()
{
AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameGraph: Clear");
for (Scope* scope : m_scopes)
{
scope->Deactivate();
@@ -9,10 +9,11 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/RHI/FrameGraphExecuter.h>
#include <Atom/RHI/Buffer.h>
#include <Atom/RHI/FrameGraph.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/FrameGraphExecuteGroup.h>
#include <Atom/RHI/FrameGraphExecuter.h>
#include <Atom/RHI/FrameGraph.h>
#include <Atom/RHI/Image.h>
#include <AzCore/Debug/EventTrace.h>
@@ -80,7 +81,7 @@ namespace AZ
void FrameGraphExecuter::End()
{
AZ_TRACE_METHOD();
AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameGraphExecuter: End");
AZ_Assert(m_pendingGroups.empty(), "Pending contexts in queue.");
m_groups.clear();
EndInternal();
@@ -181,7 +181,10 @@ namespace AZ
m_compileRequest = compileRequest;
FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompile);
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "FrameScheduler: Compile: OnFrameCompile");
FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompile);
}
FrameGraphCompileRequest frameGraphCompileRequest;
frameGraphCompileRequest.m_frameGraph = m_frameGraph.get();
@@ -193,7 +196,10 @@ namespace AZ
const MessageOutcome outcome = m_frameGraphCompiler->Compile(frameGraphCompileRequest);
if (outcome.IsSuccess())
{
FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompileEnd, *m_frameGraph);
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "FrameScheduler: Compile: OnFrameCompileEnd");
FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompileEnd, *m_frameGraph);
}
FrameGraphLogger::Log(*m_frameGraph, compileRequest.m_logVerbosity);
@@ -400,7 +406,11 @@ namespace AZ
m_scopeProducers.clear();
m_scopeProducerLookup.clear();
FrameEventBus::Event(m_device, &FrameEventBus::Events::OnFrameEnd);
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "FrameScheduler: EndFrame: OnFrameEnd");
FrameEventBus::Event(m_device, &FrameEventBus::Events::OnFrameEnd);
}
const AZStd::sys_time_t timeNowTicks = AZStd::GetTimeNowTicks();
m_cpuTimingStatistics.m_frameToFrameTime = timeNowTicks - m_lastFrameEndTime;
+8 -3
View File
@@ -10,6 +10,7 @@
*
*/
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/Device.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RHI/RHISystem.h>
@@ -213,19 +214,23 @@ namespace AZ
void RHISystem::FrameUpdate(FrameGraphCallback frameGraphCallback)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
AZ_ATOM_PROFILE_FUNCTION("RHI", "RHISystem: FrameUpdate");
{
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzRender, "main per-frame work");
m_frameScheduler.BeginFrame();
frameGraphCallback(m_frameScheduler);
/**
* This exists as a hook to enable RHI sample tests, which are allowed to queue their
* own RHI scopes to the frame scheduler. This happens prior to the RPI pass graph registration.
*/
RHISystemNotificationBus::Broadcast(&RHISystemNotificationBus::Events::OnFramePrepare, m_frameScheduler);
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "RHISystem :FrameUpdate: OnFramePrepare");
RHISystemNotificationBus::Broadcast(&RHISystemNotificationBus::Events::OnFramePrepare, m_frameScheduler);
}
RHI::MessageOutcome outcome = m_frameScheduler.Compile(m_compileRequest);
if (outcome.IsSuccess())
{
@@ -14,6 +14,7 @@
#include <RHI/CommandList.h>
#include <RHI/Conversions.h>
#include <RHI/DescriptorContext.h>
#include <Atom/RHI/CpuProfiler.h>
#include <AzCore/Debug/EventTrace.h>
namespace AZ
@@ -179,6 +180,7 @@ namespace AZ
void CommandListAllocator::Collect()
{
AZ_ATOM_PROFILE_FUNCTION("DX12", "CommandListAllocator: Collect");
for (uint32_t queueIdx = 0; queueIdx < RHI::HardwareQueueClassCount; ++queueIdx)
{
m_commandListSubAllocators[queueIdx].ForEach([](Internal::CommandListSubAllocator& commandListSubAllocator)
@@ -137,6 +137,7 @@ namespace AZ
void CommandQueueContext::End()
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
AZ_ATOM_PROFILE_FUNCTION("DX12", "CommandQueueContext: End");
QueueGpuSignals(m_frameFences[m_currentFrameIndex]);
@@ -150,7 +151,7 @@ namespace AZ
{
AZ_PROFILE_SCOPE_IDLE(AZ::Debug::ProfileCategory::AzRender, "Wait and Reset Fence");
AZ_ATOM_PROFILE_FUNCTION("RHI", "CommandQueueContext: Wait on Fences");
AZ_ATOM_PROFILE_TIME_GROUP_REGION("DX12", "CommandQueueContext: Wait on Fences");
FenceEvent event("FrameFence");
m_frameFences[m_currentFrameIndex].Wait(event);
@@ -15,6 +15,7 @@
#include <RHI/Conversions.h>
#include <RHI/Device.h>
#include <RHI/Image.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h>
namespace AZ
@@ -345,6 +346,7 @@ namespace AZ
void DescriptorContext::GarbageCollect()
{
AZ_ATOM_PROFILE_FUNCTION("DX12", "DescriptorContext: GarbageCollect");
for (const auto& itr : m_platformLimitsDescriptor->m_descriptorHeapLimits)
{
for (uint32_t shaderVisibleIdx = 0; shaderVisibleIdx < PlatformLimitsDescriptor::NumHeapFlags; ++shaderVisibleIdx)
@@ -60,6 +60,7 @@ namespace AZ
void StagingMemoryAllocator::GarbageCollect()
{
AZ_ATOM_PROFILE_FUNCTION("DX12", "StagingMemoryAllocator: GarbageCollect");
m_mediumBlockAllocators.ForEach([](MemoryLinearSubAllocator& subAllocator)
{
subAllocator.GarbageCollect();
@@ -145,7 +145,7 @@ namespace AZ
// ShaderReloadNotificationBus overrides...
void OnShaderReinitialized(const Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
///////////////////////////////////////////////////////////////////
template<typename Type>
@@ -24,6 +24,11 @@ namespace AZ
//! Connect to this EBus to get notifications whenever material objects reload.
//! The bus address is the AssetId of the MaterialAsset or MaterialTypeAsset.
//!
//! Be careful when using the parameters provided by these functions. The bus ID is an AssetId, and it's possible for the system to have
//! both *old* versions and *new reloaded* versions of the asset in memory at the same time, and they will have the same AssetId. Therefore
//! your bus Handlers could receive Reinitialized messages from multiple sources. It may be necessary to check the memory addresses of these
//! parameters against local members before using this data.
class MaterialReloadNotifications
: public EBusTraits
{
@@ -78,7 +78,7 @@ namespace AZ
// ShaderReloadNotificationBus::Handler overrides...
void OnShaderReinitialized(const Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
void LoadShader();
PassDescriptor m_passDescriptor;
@@ -78,7 +78,7 @@ namespace AZ
// ShaderReloadNotificationBus overrides...
void OnShaderReinitialized(const Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
///////////////////////////////////////////////////////////////////
void LoadShader();
@@ -88,7 +88,7 @@ namespace AZ
// ShaderReloadNotificationBus overrides...
void OnShaderReinitialized(const AZ::RPI::Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
///////////////////////////////////////////////////////////////////
// Update shader variant from m_shader. It's called whenever shader, shader asset or shader variant were changed.
@@ -22,10 +22,16 @@ namespace AZ
{
class Shader;
class ShaderAsset;
class ShaderVariant;
/**
* Connect to this EBus to get notifications whenever a Data::Instance<Shader> reloads its ShaderAsset.
* The bus address is the AssetId of the ShaderAsset.
* Connect to this EBus to get notifications whenever a shader system class reinitializes itself.
* The bus address is the AssetId of the ShaderAsset, even when the thing being reinitialized is a ShaderVariant or other shader related class.
*
* Be careful when using the parameters provided by these functions. The bus ID is an AssetId, and it's possible for the system to have
* both *old* versions and *new reloaded* versions of the asset in memory at the same time, and they will have the same AssetId. Therefore
* your bus Handlers could receive Reinitialized messages from multiple sources. It may be necessary to check the memory addresses of these
* parameters against local members before using this data.
*/
class ShaderReloadNotifications
: public EBusTraits
@@ -35,7 +41,7 @@ namespace AZ
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
typedef Data::AssetId BusIdType;
typedef Data::AssetId BusIdType;
//////////////////////////////////////////////////////////////////////////
virtual ~ShaderReloadNotifications() {}
@@ -47,7 +53,7 @@ namespace AZ
virtual void OnShaderReinitialized(const Shader& shader) { AZ_UNUSED(shader); }
//! Called when a particular shader variant is reinitialized.
virtual void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) { AZ_UNUSED(shader); AZ_UNUSED(shaderVariantId); AZ_UNUSED(shaderVariantStableId); }
virtual void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) { AZ_UNUSED(shaderVariant); }
};
typedef EBus<ShaderReloadNotifications> ShaderReloadNotificationBus;
@@ -23,10 +23,12 @@ namespace AZ
//! the RHI::PipelineStateType of the parent Shader instance. For shaders on the raster
//! pipeline, the RHI::DrawFilterTag is also provided.
class ShaderVariant final
: public Data::AssetBus::MultiHandler
{
friend class Shader;
public:
ShaderVariant() = default;
virtual ~ShaderVariant();
AZ_DEFAULT_COPY_MOVE(ShaderVariant);
//! Fills a pipeline state descriptor with settings provided by the ShaderVariant. (Note that
@@ -54,12 +56,21 @@ namespace AZ
bool IsRootVariant() const { return m_shaderVariantAsset->IsRootVariant(); }
ShaderVariantStableId GetStableId() const { return m_shaderVariantAsset->GetStableId(); }
const Data::Asset<ShaderAsset>& GetShaderAsset() const { return m_shaderAsset; }
const Data::Asset<ShaderVariantAsset>& GetShaderVariantAsset() const { return m_shaderVariantAsset; }
private:
// Called by Shader. Initializes runtime data from asset data. Returns whether the call succeeded.
bool Init(
const ShaderAsset& shaderAsset,
Data::Asset<ShaderVariantAsset> shaderVariantAsset);
const Data::Asset<ShaderAsset>& shaderAsset,
const Data::Asset<ShaderVariantAsset>& shaderVariantAsset);
// AssetBus overrides...
void OnAssetReloaded(Data::Asset<Data::AssetData> asset) override;
//! A reference to the shader asset that this is a variant of.
Data::Asset<ShaderAsset> m_shaderAsset;
// Cached state from the asset to avoid an indirection.
RHI::PipelineStateType m_pipelineStateType = RHI::PipelineStateType::Count;
@@ -11,6 +11,7 @@
*/
#include <Atom/RHI/CommandList.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RHI/FrameGraphInterface.h>
#include <Atom/RHI/RHISystemInterface.h>
@@ -78,6 +79,7 @@ namespace AZ
void GpuQuerySystem::Update()
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "GpuQuerySystem: Update");
for (auto& queryPool : m_queryPoolArray)
{
if (queryPool)
@@ -242,8 +242,16 @@ namespace AZ
// MaterialReloadNotificationBus overrides...
void Material::OnMaterialAssetReinitialized(const Data::Asset<MaterialAsset>& materialAsset)
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnMaterialAssetReinitialized %s", this, materialAsset.GetHint().c_str());
OnAssetReloaded(materialAsset);
// It's important that we don't just pass materialAsset to Init() because when reloads occur,
// it's possible for old Asset objects to hang around and report reinitialization, so materialAsset
// might be stale data.
if (materialAsset.Get() == m_materialAsset.Get())
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnMaterialAssetReinitialized %s", this, materialAsset.GetHint().c_str());
OnAssetReloaded(m_materialAsset);
}
}
///////////////////////////////////////////////////////////////////
@@ -259,8 +267,6 @@ namespace AZ
void Material::OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset)
{
// TODO: I think we should make Shader handle OnShaderAssetReinitialized and treat it just like the shader reloaded.
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str());
// Note that it might not be strictly necessary to reinitialize the entire material, we might be able to get away with
// just bumping the m_currentChangeId or some other minor updates. But it's pretty hard to know what exactly needs to be
@@ -268,9 +274,9 @@ namespace AZ
OnAssetReloaded(m_materialAsset);
}
void Material::OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& /*shaderVariantId*/, ShaderVariantStableId shaderVariantStableId)
void Material::OnShaderVariantReinitialized(const ShaderVariant& shaderVariant)
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderVariantReinitialized %s variant %u", this, shader.GetAsset().GetHint().c_str(), shaderVariantStableId.GetIndex());
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderVariantReinitialized %s", this, shaderVariant.GetShaderVariantAsset().GetHint().c_str());
// Note that it would be better to check the shaderVariantId to see if that variant is relevant to this particular material before reinitializing it.
// There could be hundreds or even thousands of variants for a shader, but only one of those variants will be used by any given material. So we could
@@ -241,9 +241,8 @@ namespace AZ
LoadShader();
}
void ComputePass::OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId)
void ComputePass::OnShaderVariantReinitialized(const ShaderVariant&)
{
AZ_UNUSED(shader); AZ_UNUSED(shaderVariantId); AZ_UNUSED(shaderVariantStableId);
LoadShader();
}
@@ -57,7 +57,7 @@ namespace AZ
LoadShader();
}
void FullscreenTrianglePass::OnShaderVariantReinitialized(const Shader&, const ShaderVariantId&, ShaderVariantStableId)
void FullscreenTrianglePass::OnShaderVariantReinitialized(const ShaderVariant&)
{
LoadShader();
}
@@ -61,6 +61,11 @@ namespace AZ
{
const PassAttachmentBinding& binding = m_attachmentBindings[slotIndex];
if (!binding.m_attachment)
{
continue;
}
// Handle the depth-stencil attachment. There should be only one.
if (binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::DepthStencil)
{
@@ -98,6 +103,10 @@ namespace AZ
{
continue;
}
if (!binding.m_attachment)
{
continue;
}
if (binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::RenderTarget
|| binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::DepthStencil)
@@ -124,12 +124,9 @@ namespace AZ
RefreshShaderVariant();
}
void PipelineStateForDraw::OnShaderVariantReinitialized(
[[maybe_unused]] const Shader& shader,
const ShaderVariantId& shaderVariantId,
[[maybe_unused]] ShaderVariantStableId shaderVariantStableId)
void PipelineStateForDraw::OnShaderVariantReinitialized(const ShaderVariant& shaderVariant)
{
if(shaderVariantId == m_shaderVariantId)
if(shaderVariant.GetShaderVariantId() == m_shaderVariantId)
{
RefreshShaderVariant();
}
@@ -282,24 +282,27 @@ namespace AZ
m_rhiSystem.FrameUpdate(
[this](RHI::FrameGraphBuilder& frameGraphBuilder)
{
// Pass system's frame update, which includes the logic of adding scope producers, has to be added here since the scope producers only can be added to the frame
// when frame started which cleans up previous scope producers.
m_passSystem.FrameUpdate(frameGraphBuilder);
{
// Pass system's frame update, which includes the logic of adding scope producers, has to be added here since the
// scope producers only can be added to the frame when frame started which cleans up previous scope producers.
m_passSystem.FrameUpdate(frameGraphBuilder);
// Update View Srgs
for (auto& scenePtr : m_scenes)
{
scenePtr->UpdateSrgs();
}
});
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "RPISystem: FrameEnd");
m_dynamicDraw.FrameEnd();
m_passSystem.FrameEnd();
// Update View Srgs
for (auto& scenePtr : m_scenes)
{
scenePtr->UpdateSrgs();
scenePtr->OnFrameEnd();
}
});
m_dynamicDraw.FrameEnd();
m_passSystem.FrameEnd();
for (auto& scenePtr : m_scenes)
{
scenePtr->OnFrameEnd();
}
m_renderTick++;
+17 -8
View File
@@ -404,6 +404,7 @@ namespace AZ
{
AZ_PROFILE_SCOPE(Debug::ProfileCategory::AzRender, "WaitForSimulationCompletion");
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "WaitForSimulationCompletion");
WaitAndCleanCompletionJob(m_simulationCompletion);
}
@@ -420,12 +421,15 @@ namespace AZ
// Get active pipelines which need to be rendered and notify them frame started
AZStd::vector<RenderPipelinePtr> activePipelines;
for (auto& pipeline : m_pipelines)
{
if (pipeline->NeedsRender())
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "OnStartFrame");
for (auto& pipeline : m_pipelines)
{
activePipelines.push_back(pipeline);
pipeline->OnStartFrame(tickInfo);
if (pipeline->NeedsRender())
{
activePipelines.push_back(pipeline);
pipeline->OnStartFrame(tickInfo);
}
}
}
@@ -444,7 +448,7 @@ namespace AZ
{
AZ_PROFILE_SCOPE(Debug::ProfileCategory::AzRender, "Setup Views");
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Setup Views");
// Collect persistent views from all pipelines to be rendered
AZStd::map<ViewPtr, RHI::DrawListMask> persistentViews;
@@ -490,7 +494,6 @@ namespace AZ
{
const auto renderLambda = [this, &fp]()
{
AZ_PROFILE_SCOPE_DYNAMIC(Debug::ProfileCategory::AzRender, "renderJob - fp:%s", fp->RTTI_GetTypeName());
fp->Render(m_renderPacket);
};
@@ -526,12 +529,14 @@ namespace AZ
// Add dynamic draw data for all the views
if (m_dynamicDrawSystem)
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "DynamicDraw SubmitDrawData");
m_dynamicDrawSystem->SubmitDrawData(this, m_renderPacket.m_views);
}
}
{
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzRender, "FinalizeDrawLists");
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "FinalizeDrawLists");
if (jobPolicy == RHI::JobPolicy::Serial)
{
for (auto& view : m_renderPacket.m_views)
@@ -542,7 +547,6 @@ namespace AZ
else
{
AZ::JobCompletion* finalizeDrawListsCompletion = aznew AZ::JobCompletion();
AZ_PROFILE_EVENT_BEGIN(Debug::ProfileCategory::AzRender, "StartFinalizeDrawListsJobs");
for (auto& view : m_renderPacket.m_views)
{
const auto finalizeDrawListsLambda = [view]()
@@ -559,11 +563,15 @@ namespace AZ
}
}
SceneNotificationBus::Event(GetId(), &SceneNotification::OnEndPrepareRender);
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Scene OnEndPrepareRender");
SceneNotificationBus::Event(GetId(), &SceneNotification::OnEndPrepareRender);
}
}
void Scene::OnFrameEnd()
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: OnFrameEnd");
for (auto& pipeline : m_pipelines)
{
if (pipeline->NeedsRender())
@@ -702,6 +710,7 @@ namespace AZ
void Scene::RebuildPipelineStatesLookup()
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: RebuildPipelineStatesLookup");
m_pipelineStatesLookup.clear();
AZStd::queue<ParentPass*> parents;
@@ -68,7 +68,7 @@ namespace AZ
AZStd::unique_lock<decltype(m_variantCacheMutex)> lock(m_variantCacheMutex);
m_shaderVariants.clear();
}
m_rootVariant.Init(shaderAsset, shaderAsset.GetRootVariant());
m_rootVariant.Init(Data::Asset<ShaderAsset>{&shaderAsset, AZ::Data::AssetLoadBehavior::PreLoad}, shaderAsset.GetRootVariant());
if (m_pipelineLibraryHandle.IsNull())
{
@@ -154,7 +154,14 @@ namespace AZ
{
AZ_Assert(shaderVariantAsset, "Reloaded ShaderVariantAsset is null");
const ShaderVariantStableId stableId = shaderVariantAsset->GetStableId();
const ShaderVariantId& shaderVariantId = shaderVariantAsset->GetShaderVariantId();
// We make a copy of the updated variant because OnShaderVariantReinitialized must not be called inside
// m_variantCacheMutex or deadlocks may occur.
// Or if there is an error, we leave this object in its default state to indicate there was an error.
// [GFX TODO] We really should have a dedicated message/event for this, but that will be covered by a future task where
// we will merge ShaderReloadNotificationBus messages into one. For now, we just indicate the error by passing an empty ShaderVariant,
// all our call sites don't use this data anyway.
ShaderVariant updatedVariant;
if (isError)
{
@@ -165,7 +172,7 @@ namespace AZ
return;
}
AZStd::unique_lock<decltype(m_variantCacheMutex)> lock(m_variantCacheMutex);
m_shaderVariants.erase(stableId);
m_shaderVariants.erase(stableId);
}
else
{
@@ -178,23 +185,26 @@ namespace AZ
{
ShaderVariant& shaderVariant = iter->second;
if (!shaderVariant.Init(*m_asset.Get(), shaderVariantAsset))
if (!shaderVariant.Init(m_asset, shaderVariantAsset))
{
AZ_Error("Shader", false, "Failed to init shaderVariant with StableId=%u", shaderVariantAsset->GetStableId());
m_shaderVariants.erase(stableId);
}
else
{
updatedVariant = shaderVariant;
}
}
else
{
//This is the first time the shader variant asset comes to life.
ShaderVariant newVariant;
newVariant.Init(*m_asset, shaderVariantAsset);
m_shaderVariants.emplace(stableId, newVariant);
updatedVariant.Init(m_asset, shaderVariantAsset);
m_shaderVariants.emplace(stableId, updatedVariant);
}
}
//Even if there was an error, the interested parties should be notified.
ShaderReloadNotificationBus::Event(m_asset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this, shaderVariantId, stableId);
// [GFX TODO] It might make more sense to call OnShaderReinitialized here
ShaderReloadNotificationBus::Event(m_asset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, updatedVariant);
}
///////////////////////////////////////////////////////////////////
@@ -203,10 +213,15 @@ namespace AZ
// ShaderReloadNotificationBus overrides...
void Shader::OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset)
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Shader::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str());
// When reloads occur, it's possible for old Asset objects to hang around and report reinitialization,
// so we can reduce unnecessary reinitialization in that case.
if (shaderAsset.Get() == m_asset.Get())
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Shader::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str());
Init(*m_asset.Get());
ShaderReloadNotificationBus::Event(shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderReinitialized, *this);
Init(*m_asset.Get());
ShaderReloadNotificationBus::Event(shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderReinitialized, *this);
}
}
///////////////////////////////////////////////////////////////////
@@ -340,7 +355,7 @@ namespace AZ
}
ShaderVariant newVariant;
newVariant.Init(*m_asset, shaderVariantAsset);
newVariant.Init(m_asset, shaderVariantAsset);
m_shaderVariants.emplace(shaderVariantStableId, newVariant);
return m_shaderVariants.at(shaderVariantStableId);
@@ -9,11 +9,13 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/RPI.Public/Shader/ShaderVariant.h>
#include <Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h>
#include <Atom/RPI.Public/Shader/ShaderReloadDebugTracker.h>
#include <Atom/RHI/DrawListTagRegistry.h>
#include <Atom/RHI/RHISystemInterface.h>
#include <Atom/RHI.Reflect/ShaderStageFunction.h>
namespace AZ
@@ -21,15 +23,26 @@ namespace AZ
namespace RPI
{
bool ShaderVariant::Init(
const ShaderAsset& shaderAsset,
Data::Asset<ShaderVariantAsset> shaderVariantAsset)
{
m_pipelineStateType = shaderAsset.GetPipelineStateType();
m_pipelineLayoutDescriptor = shaderAsset.GetPipelineLayoutDescriptor();
const Data::Asset<ShaderAsset>& shaderAsset,
const Data::Asset<ShaderVariantAsset>& shaderVariantAsset)
{
Data::AssetBus::MultiHandler::BusDisconnect();
Data::AssetBus::MultiHandler::BusConnect(shaderAsset.GetId());
Data::AssetBus::MultiHandler::BusConnect(shaderVariantAsset.GetId());
m_shaderAsset = shaderAsset;
m_pipelineStateType = shaderAsset->GetPipelineStateType();
m_pipelineLayoutDescriptor = shaderAsset->GetPipelineLayoutDescriptor();
m_shaderVariantAsset = shaderVariantAsset;
return true;
}
ShaderVariant::~ShaderVariant()
{
Data::AssetBus::MultiHandler::BusDisconnect();
}
void ShaderVariant::ConfigurePipelineState(RHI::PipelineStateDescriptor& descriptor) const
{
descriptor.m_pipelineLayoutDescriptor = m_pipelineLayoutDescriptor;
@@ -78,5 +91,25 @@ namespace AZ
{
return m_shaderVariantAsset->GetOutputContract();
}
void ShaderVariant::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderVariant::OnAssetReloaded %s", this, asset.GetHint().c_str());
if (asset.GetAs<ShaderVariantAsset>())
{
Data::Asset<ShaderVariantAsset> shaderVariantAsset = { asset.GetAs<ShaderVariantAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
Init(m_shaderAsset, shaderVariantAsset);
ShaderReloadNotificationBus::Event(m_shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this);
}
if (asset.GetAs<ShaderAsset>())
{
Data::Asset<ShaderAsset> shaderAsset = { asset.GetAs<ShaderAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
Init(shaderAsset, m_shaderVariantAsset);
ShaderReloadNotificationBus::Event(m_shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this);
}
}
} // namespace RPI
} // namespace AZ
@@ -323,9 +323,8 @@ namespace AZ
void ShaderVariantAsyncLoader::Reset()
{
// [GFX TODO ATOM-14544] Idealy we want to be able to reset the ShaderVariantAsyncLoader but this is causing some problems that need to be worked out first.
//Shutdown();
//Init();
Shutdown();
Init();
}
///////////////////////////////////////////////////////////////////
@@ -115,12 +115,19 @@ namespace AZ
}
}
void MaterialAsset::OnMaterialTypeAssetReinitialized(const Data::Asset<MaterialTypeAsset>&)
void MaterialAsset::OnMaterialTypeAssetReinitialized(const Data::Asset<MaterialTypeAsset>& materialTypeAsset)
{
// MaterialAsset doesn't need to reinitialize any of its own data when MaterialTypeAsset reinitializes,
// because all it depends on is the MaterialTypeAsset reference, rather than the data inside it.
// Ultimately it's the Material that cares about these changes, so we just forward any signal we get.
MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialAssetReinitialized, Data::Asset<MaterialAsset>{this, AZ::Data::AssetLoadBehavior::PreLoad});
// When reloads occur, it's possible for old Asset objects to hang around and report reinitialization,
// so we can reduce unnecessary reinitialization in that case.
if (materialTypeAsset.Get() == m_materialTypeAsset.Get())
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnMaterialTypeAssetReinitialized %s", this, materialTypeAsset.GetHint().c_str());
// MaterialAsset doesn't need to reinitialize any of its own data when MaterialTypeAsset reinitializes,
// because all it depends on is the MaterialTypeAsset reference, rather than the data inside it.
// Ultimately it's the Material that cares about these changes, so we just forward any signal we get.
MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialAssetReinitialized, Data::Asset<MaterialAsset>{this, AZ::Data::AssetLoadBehavior::PreLoad});
}
}
void MaterialAsset::ReinitializeMaterialTypeAsset(Data::Asset<Data::AssetData> asset)
@@ -13,6 +13,7 @@
#pragma once
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
namespace AZ
{
@@ -56,6 +57,16 @@ namespace AZ
ImGuiTextFilter m_timedRegionFilter;
GroupRegionMap m_groupRegionMap;
// Pause cpu profiling. The profiler will show the statistics of the last frame before pause
bool m_paused = false;
// Total frames need to be saved
int m_captureFrameCount = 1;
AZ::RHI::CpuTimingStatistics m_cpuTimingStatisticsWhenPause;
AZStd::string m_lastCapturedFilePath;
};
} // namespace Render
}
@@ -10,7 +10,10 @@
*
*/
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
#include <Atom/Feature/Utils/ProfilingCaptureBus.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <AzCore/IO/SystemFile.h> // For AZ_MAX_PATH_LEN
#include <AzCore/std/time.h>
namespace AZ
{
@@ -34,16 +37,42 @@ namespace AZ
}
}
inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics)
inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics)
{
// Cache the value to detect if it was changed by ImGui(user pressed 'x')
const bool cachedShowCpuProfiler = keepDrawing;
const ImVec2 windowSize(640.0f, 480.0f);
ImGui::SetNextWindowSize(windowSize, ImGuiCond_Once);
bool captureToFile = false;
if (ImGui::Begin("Cpu Profiler", &keepDrawing, ImGuiWindowFlags_None))
{
UpdateGroupRegionMap();
m_paused = !AZ::RHI::CpuProfiler::Get()->IsProfilerEnabled();
if (ImGui::Button(m_paused?"Resume":"Pause"))
{
m_paused = !m_paused;
AZ::RHI::CpuProfiler::Get()->SetProfilerEnabled(!m_paused);
}
// Update region map and cache the input cpu timing statistics when the profiling is not paused
if (!m_paused)
{
UpdateGroupRegionMap();
m_cpuTimingStatisticsWhenPause = currentCpuTimingStatistics;
}
if (ImGui::Button("Capture"))
{
captureToFile = true;
}
if (!m_lastCapturedFilePath.empty())
{
ImGui::SameLine();
ImGui::Text(m_lastCapturedFilePath.c_str());
}
const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics = m_cpuTimingStatisticsWhenPause;
const AZStd::sys_time_t ticksPerSecond = AZStd::GetTimeTicksPerSecond();
@@ -51,7 +80,7 @@ namespace AZ
{
// Note: converting to microseconds integer before converting to milliseconds float
const float timeInMs = static_cast<float>((duration * 1000) / (ticksPerSecond / 1000)) / 1000.0f;
ImGui::Text("%.1f ms", timeInMs);
ImGui::Text("%.2f ms", timeInMs);
};
const auto ShowRow = [ticksPerSecond, &ShowTimeInMs](const char* regionLabel, AZStd::sys_time_t duration)
@@ -158,6 +187,20 @@ namespace AZ
}
ImGui::End();
if (captureToFile)
{
AZStd::sys_time_t timeNow = AZStd::GetTimeNowSecond();
AZStd::string timeString;
AZStd::to_string(timeString, timeNow);
u64 currentTick = AZ::RPI::RPISystemInterface::Get()->GetCurrentTick();
AZStd::string frameDataFilePath = AZStd::string::format("@user@/CpuProfiler/%s_%llu.json", timeString.c_str(), currentTick);
char resolvedPath[AZ_MAX_PATH_LEN];
AZ::IO::FileIOBase::GetInstance()->ResolvePath(frameDataFilePath.c_str(), resolvedPath, AZ_MAX_PATH_LEN);
m_lastCapturedFilePath = resolvedPath;
AZ::Render::ProfilingCaptureRequestBus::Broadcast(&AZ::Render::ProfilingCaptureRequestBus::Events::CaptureCpuProfilingStatistics,
frameDataFilePath);
}
// Toggle if the bool isn't the same as the cached value
if (cachedShowCpuProfiler != keepDrawing)
{
@@ -143,6 +143,13 @@ namespace AZ
//! Sets the type of Pcf (percentage-closer filtering) to use.
virtual void SetPcfMethod(PcfMethod method) = 0;
//! Gets the Esm exponent. Higher values produce a steeper falloff between light and shadow.
virtual float GetEsmExponent() const = 0;
//! Sets the Esm exponent. Higher values produce a steeper falloff between light and shadow.
virtual void SetEsmExponent(float exponent) = 0;
};
//! The EBus for requests to for setting and getting light component properties.
@@ -66,6 +66,7 @@ namespace AZ
float m_boundaryWidthInDegrees = 0.25f;
uint16_t m_predictionSampleCount = 4;
uint16_t m_filteringSampleCount = 12;
float m_esmExponent = 87.0f;
// The following functions provide information to an EditContext...
@@ -124,6 +125,8 @@ namespace AZ
//! Returns true if pcf boundary search is disabled.
bool IsPcfBoundarySearchDisabled() const;
//! Returns true if exponential shadow maps are disabled.
bool IsEsmDisabled() const;
};
}
}
@@ -21,7 +21,7 @@ namespace AZ
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<AreaLightComponentConfig, ComponentConfig>()
->Version(5) // ATOM-14637
->Version(6) // ATOM-15654
->Field("LightType", &AreaLightComponentConfig::m_lightType)
->Field("Color", &AreaLightComponentConfig::m_color)
->Field("IntensityMode", &AreaLightComponentConfig::m_intensityMode)
@@ -41,7 +41,8 @@ namespace AZ
->Field("Softening Boundary Width", &AreaLightComponentConfig::m_boundaryWidthInDegrees)
->Field("Prediction Sample Count", &AreaLightComponentConfig::m_predictionSampleCount)
->Field("Filtering Sample Count", &AreaLightComponentConfig::m_filteringSampleCount)
->Field("Pcf Method", &AreaLightComponentConfig::m_pcfMethod);
->Field("Pcf Method", &AreaLightComponentConfig::m_pcfMethod)
->Field("Esm Exponent", &AreaLightComponentConfig::m_esmExponent)
;
}
}
@@ -200,5 +201,11 @@ namespace AZ
return m_pcfMethod != PcfMethod::BoundarySearch;
}
bool AreaLightComponentConfig::IsEsmDisabled() const
{
return !(m_shadowFilterMethod == ShadowFilterMethod::Esm || m_shadowFilterMethod == ShadowFilterMethod::EsmPcf);
}
}
}
@@ -84,7 +84,9 @@ namespace AZ::Render
->Event("SetFilteringSampleCount", &AreaLightRequestBus::Events::SetFilteringSampleCount)
->Event("GetPcfMethod", &AreaLightRequestBus::Events::GetPcfMethod)
->Event("SetPcfMethod", &AreaLightRequestBus::Events::SetPcfMethod)
->Event("GetEsmExponent", &AreaLightRequestBus::Events::GetEsmExponent)
->Event("SetEsmExponent", &AreaLightRequestBus::Events::SetEsmExponent)
->VirtualProperty("AttenuationRadius", "GetAttenuationRadius", "SetAttenuationRadius")
->VirtualProperty("Color", "GetColor", "SetColor")
->VirtualProperty("EmitsLightBothDirections", "GetEmitsLightBothDirections", "SetEmitsLightBothDirections")
@@ -101,8 +103,9 @@ namespace AZ::Render
->VirtualProperty("SofteningBoundaryWidthAngle", "GetSofteningBoundaryWidthAngle", "SetSofteningBoundaryWidthAngle")
->VirtualProperty("PredictionSampleCount", "GetPredictionSampleCount", "SetPredictionSampleCount")
->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount")
->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod");
;
->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod")
->VirtualProperty("EsmExponent", "GetEsmExponent", "SetEsmExponent");
;
}
}
@@ -314,6 +317,7 @@ namespace AZ::Render
m_lightShapeDelegate->SetPredictionSampleCount(m_configuration.m_predictionSampleCount);
m_lightShapeDelegate->SetFilteringSampleCount(m_configuration.m_filteringSampleCount);
m_lightShapeDelegate->SetPcfMethod(m_configuration.m_pcfMethod);
m_lightShapeDelegate->SetEsmExponent(m_configuration.m_esmExponent);
}
}
}
@@ -565,6 +569,20 @@ namespace AZ::Render
}
}
float AreaLightComponentController::GetEsmExponent() const
{
return m_configuration.m_esmExponent;
}
void AreaLightComponentController::SetEsmExponent(float esmExponent)
{
m_configuration.m_esmExponent = esmExponent;
if (m_lightShapeDelegate)
{
m_lightShapeDelegate->SetEsmExponent(esmExponent);
}
}
void AreaLightComponentController::CreateLightShapeDelegate()
{
switch (m_configuration.m_lightType)
@@ -92,6 +92,8 @@ namespace AZ
void SetFilteringSampleCount(uint32_t count) override;
PcfMethod GetPcfMethod() const override;
void SetPcfMethod(PcfMethod method) override;
float GetEsmExponent() const override;
void SetEsmExponent(float exponent) override;
void HandleDisplayEntityViewport(
const AzFramework::ViewportInfo& viewportInfo,
@@ -175,5 +175,13 @@ namespace AZ::Render
}
}
void DiskLightDelegate::SetEsmExponent(float exponent)
{
if (GetShadowsEnabled() && GetLightHandle().IsValid())
{
GetFeatureProcessor()->SetEsmExponent(GetLightHandle(), exponent);
}
}
} // namespace AZ::Render
@@ -51,6 +51,7 @@ namespace AZ
void SetPredictionSampleCount(uint32_t count) override;
void SetFilteringSampleCount(uint32_t count) override;
void SetPcfMethod(PcfMethod method) override;
void SetEsmExponent(float exponent) override;
private:
@@ -179,8 +179,19 @@ namespace AZ
->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search")
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled);
;
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled)
->DataElement(
Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_esmExponent, "Esm Exponent",
"Exponent used by Esm shadows. "
"Larger values increase the sharpness of the border between lit and unlit areas.")
->Attribute(Edit::Attributes::Min, 50.0f)
->Attribute(Edit::Attributes::Max, 5000.0f)
->Attribute(AZ::Edit::Attributes::Decimals, 0)
->Attribute(AZ::Edit::Attributes::SliderCurveMidpoint, 0.05f)
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsEsmDisabled)
;
}
}
@@ -63,6 +63,7 @@ namespace AZ
void SetPredictionSampleCount([[maybe_unused]] uint32_t count) override {};
void SetFilteringSampleCount([[maybe_unused]] uint32_t count) override {};
void SetPcfMethod([[maybe_unused]] PcfMethod method) override {};
void SetEsmExponent([[maybe_unused]] float esmExponent) override{};
protected:
void InitBase(EntityId entityId);
@@ -85,6 +85,8 @@ namespace AZ
virtual void SetFilteringSampleCount(uint32_t count) = 0;
//! Sets the Pcf (Percentage closer filtering) method to use.
virtual void SetPcfMethod(PcfMethod method) = 0;
//! Sets the Esm exponent to use. Higher values produce a steeper falloff between light and shadow.
virtual void SetEsmExponent(float exponent) = 0;
};
} // namespace Render
} // namespace AZ
@@ -122,5 +122,14 @@ namespace AZ
}
}
void SphereLightDelegate::SetEsmExponent(float esmExponent)
{
if (GetShadowsEnabled() && GetLightHandle().IsValid())
{
GetFeatureProcessor()->SetEsmExponent(GetLightHandle(), esmExponent);
}
}
} // namespace Render
} // namespace AZ
@@ -41,6 +41,7 @@ namespace AZ
void SetPredictionSampleCount(uint32_t count) override;
void SetFilteringSampleCount(uint32_t count) override;
void SetPcfMethod(PcfMethod method) override;
void SetEsmExponent(float esmExponent) override;
private:
@@ -286,9 +286,13 @@ namespace Blast
// Create damage and actor render managers
m_damageManager = AZStd::make_unique<DamageManager>(blastMaterial, m_family->GetActorTracker());
m_actorRenderManager = AZStd::make_unique<ActorRenderManager>(
AZ::RPI::Scene::GetFeatureProcessorForEntity<AZ::Render::MeshFeatureProcessorInterface>(GetEntityId()),
m_meshDataComponent, GetEntityId(), m_blastAsset->GetPxAsset()->getChunkCount(), AZ::Vector3(transform.GetUniformScale()));
if (m_meshDataComponent)
{
m_actorRenderManager = AZStd::make_unique<ActorRenderManager>(
AZ::RPI::Scene::GetFeatureProcessorForEntity<AZ::Render::MeshFeatureProcessorInterface>(GetEntityId()),
m_meshDataComponent, GetEntityId(), m_blastAsset->GetPxAsset()->getChunkCount(), AZ::Vector3(transform.GetUniformScale()));
}
// Spawn the family
m_family->Spawn(transform);
@@ -540,7 +544,11 @@ namespace Blast
void BlastFamilyComponent::OnActorCreated([[maybe_unused]] const BlastFamily& family, const BlastActor& actor)
{
m_actorRenderManager->OnActorCreated(actor);
if (m_actorRenderManager)
{
m_actorRenderManager->OnActorCreated(actor);
}
m_solver->notifyActorCreated(*actor.GetTkActor().getActorLL());
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
@@ -576,7 +584,11 @@ namespace Blast
}
m_solver->notifyActorDestroyed(*actor.GetTkActor().getActorLL());
m_actorRenderManager->OnActorDestroyed(actor);
if (m_actorRenderManager)
{
m_actorRenderManager->OnActorDestroyed(actor);
}
}
// Update positions of entities with render meshes corresponding to their right dynamic bodies.
@@ -826,7 +826,7 @@ enum class NetworkProperties
#}
{% macro DefineNetworkPropertyBehaviorReflection(Component, ReplicateFrom, ReplicateTo, ClassName) %}
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
{% if (Property.attrib['IsPublic'] | booleanTrue == true) and (Property.attrib['GenerateEventBindings'] | booleanTrue == true) -%}
{% if (Property.attrib['IsPublic'] | booleanTrue == true) and (Property.attrib['ExposeToScript'] | booleanTrue == true) -%}
// {{ UpperFirst(Property.attrib['Name']) }}: Replicate from {{ ReplicateFrom }} to {{ ReplicateTo }}
{% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %}
->Method("Get{{ UpperFirst(Property.attrib['Name']) }}", [](AZ::EntityId id, int32_t index) -> {{ Property.attrib['Type'] }}
@@ -17,7 +17,7 @@
<Include File="Source/NetworkInput/NetworkInputMigrationVector.h"/>
<Include File="AzNetworking/DataStructures/ByteBuffer.h"/>
<NetworkProperty Type="Multiplayer::ClientInputId" Name="LastInputId" Init="Multiplayer::ClientInputId{ 0 }" ReplicateFrom="Authority" ReplicateTo="Server" 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="Server" IsRewindable="false" IsPredictable="false" IsPublic="false" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="false" />
<RemoteProcedure Name="SendClientInput" InvokeFrom="Autonomous" HandleOn="Authority" IsPublic="true" IsReliable="false" GenerateEventBindings="false" Description="Client to server move / input RPC">
<Param Type="Multiplayer::NetworkInputArray" Name="inputArray" />
@@ -12,12 +12,12 @@
<Include File="Multiplayer/MultiplayerTypes.h"/>
<NetworkProperty Type="AZ::Quaternion" Name="rotation" Init="AZ::Quaternion::CreateIdentity()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
<NetworkProperty Type="AZ::Vector3" Name="translation" Init="AZ::Vector3::CreateZero()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
<NetworkProperty Type="float" Name="scale" Init="1.0f" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
<NetworkProperty Type="uint8_t" Name="resetCount" Init="0" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="false" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
<NetworkProperty Type="NetEntityId" Name="parentEntityId" Init="InvalidNetEntityId" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
<NetworkProperty Type="int32_t" Name="parentAttachmentBoneId" Init="-1" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
<NetworkProperty Type="AZ::Quaternion" Name="rotation" Init="AZ::Quaternion::CreateIdentity()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
<NetworkProperty Type="AZ::Vector3" Name="translation" Init="AZ::Vector3::CreateZero()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
<NetworkProperty Type="float" Name="scale" Init="1.0f" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
<NetworkProperty Type="uint8_t" Name="resetCount" Init="0" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="false" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
<NetworkProperty Type="NetEntityId" Name="parentEntityId" Init="InvalidNetEntityId" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
<NetworkProperty Type="int32_t" Name="parentAttachmentBoneId" Init="-1" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
<!--
<ArchetypeProperty Type="bool" Name="snapToGround" Init="false" ExposeToEditor="true" />
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:056f3c42226567848b7b7bd959cde0dccdcf63a79700743e55436eae35520a28
size 80
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5fc10f1dd377cc2663faaa6aa5503aadb8288179cddc46bb3379337167c150fc
size 76
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:785988d40e9af3f1f6adccc10a5a6fa1f6a78b6f6bb10647acf0f3997cd14834
size 80
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:76017bdaf559051a5ec6fb46a9132020ad54d35c1bdaf39511e52f0d3faeffe2
size 87
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2b8efdd98b365874375ea80ee02c3b8e3d951aa5f74fe50fb0cfd2a431395b23
size 85
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fa1ed0cda25890a36a3f2c9f4bd2cbfbb4cef0198258f1b33a0ad3fb804c860c
size 91
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:38cff841ea29a428729b79667672d3825188b9eec74ce0be324c5a072958c63d
size 68
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cc9ad675bca0b1446b9d3ad9b6bf53b1348f7dd96e00eb256744f82273b9f9da
size 76
@@ -1,173 +0,0 @@
----------------------------------------------------------------------------------------------------
--
-- 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.
--
--
----------------------------------------------------------------------------------------------------
Constraint =
{
Properties=
{
radius = 0.03,
damping = 0,
bNoSelfCollisions = 1,
bUseEntityFrame=1,
max_pull_force=0,
max_bend_torque=0,
bConstrainToLine=0,
bConstrainToPlane=0,
bConstrainFully=1,
bNoRotation=0,
Limits = {
x_min = 0,
x_max = 0,
yz_min = 0,
yz_max = 0,
}
},
numUpdates = 0,
Editor=
{
Icon="Magnet.bmp",
ShowBounds = 1,
},
}
function Constraint:OnReset()
--Log("%s:OnReset() idEnt: %s idConstr: %s broken: %s", self:GetName(), tostring(self.idEnt),
-- tostring(self.idConstr), tostring(self.broken))
--if (self.idConstr) then
--System.GetEntity(self.idEnt):SetPhysicParams(PHYSICPARAM_REMOVE_CONSTRAINT, { id=self.idConstr })
--end
self.idEnt = nil
self.idConstr = nil
self.broken = nil
self.numUpdates = 0
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
function Constraint:Apply()
--Log("%s:Apply() idEnt: %s idConstr: %s broken: %s", self:GetName(), tostring(self.idEnt),
-- tostring(self.idConstr), tostring(self.broken))
local ConstraintParams = {pivot={},frame0={},frame1={}};
if self.idEnt then
elseif (not self.broken) then
local ents = Physics.SamplePhysEnvironment(self:GetPos(), self.Properties.radius);
if (ents[1] and ents[6]) then
CopyVector(ConstraintParams.pivot, self:GetPos());
if self.Properties.bUseEntityFrame==1 then
CopyVector(ConstraintParams.frame1, ents[1]:GetAngles());
else
CopyVector(ConstraintParams.frame1, self:GetAngles());
end
CopyVector(ConstraintParams.frame0, ConstraintParams.frame1);
ConstraintParams.entity_part_id_1 = ents[2];
ConstraintParams.phys_entity_id = ents[6];
ConstraintParams.entity_part_id_2 = ents[5];
ConstraintParams.xmin = self.Properties.Limits.x_min;
ConstraintParams.xmax = self.Properties.Limits.x_max;
ConstraintParams.yzmin = self.Properties.Limits.yz_min;
ConstraintParams.yzmax = self.Properties.Limits.yz_max;
ConstraintParams.ignore_buddy = self.Properties.bNoSelfCollisions;
ConstraintParams.damping = self.Properties.damping;
ConstraintParams.sensor_size = self.Properties.radius;
ConstraintParams.max_pull_force = self.Properties.max_pull_force;
ConstraintParams.max_bend_torque = self.Properties.max_bend_torque;
ConstraintParams.line = self.Properties.bConstrainToLine;
ConstraintParams.plane = self.Properties.bConstrainToPlane;
ConstraintParams.no_rotation = self.Properties.bNoRotation;
ConstraintParams.full = self.Properties.bConstrainFully;
self.idConstr = ents[1]:SetPhysicParams(PHYSICPARAM_CONSTRAINT, ConstraintParams);
self.idEnt = ents[1].id;
else
self:SetTimer(1,1);
end
end
end
function Constraint:OnTimer()
if (self.numUpdates < 10) then
self:Apply();
self.numUpdates = self.numUpdates+1;
end
end
function Constraint:OnLevelLoaded()
--Log("%s:OnLevelLoaded() idEnt: %s idConstr: %s broken: %s", self:GetName(), tostring(self.idEnt),
-- tostring(self.idConstr), tostring(self.broken))
if ((not self.broken) and (not self.idConstr)) then
self.numUpdates = 0
self.idEnt = nil
self.idConstr = nil
self:Apply()
end
end
function Constraint:OnPropertyChange()
self:OnReset()
end
function Constraint:OnSpawn()
self:OnReset()
end
function Constraint:Event_ConstraintBroken(sender)
--Log("%s:Event_ConstraintBroken() idEnt: %s idConstr: %s broken: %s", self:GetName(), tostring(self.idEnt),
-- tostring(self.idConstr), tostring(self.broken))
if self.idEnt then
System.GetEntity(self.idEnt):SetPhysicParams(PHYSICPARAM_REMOVE_CONSTRAINT, { id=self.idConstr });
self.idEnt = nil
self.idConstr = nil
end
self.broken = true
self:KillTimer(1)
BroadcastEvent(self, "ConstraintBroken")
end
function Constraint:OnSave( props )
--Log("%s:OnSave() idEnt: %s idConstr: %s broken: %s", self:GetName(), tostring(self.idEnt),
-- tostring(self.idConstr), tostring(self.broken))
props.broken = self.broken
props.idEnt = self.idEnt
props.idConstr = self.idConstr
end
function Constraint:OnLoad( props )
self.broken = props.broken
self.idEnt = props.idEnt
self.idConstr = props.idConstr
--Log("%s:OnLoad() idEnt: %s idConstr: %s broken: %s", self:GetName(), tostring(self.idEnt),
-- tostring(self.idConstr), tostring(self.broken))
end
function Constraint:OnDestroy()
end
Constraint.FlowEvents =
{
Inputs =
{
ConstraintBroken = { Constraint.Event_ConstraintBroken, "bool" },
},
Outputs =
{
ConstraintBroken = "bool",
},
}
@@ -1,289 +0,0 @@
----------------------------------------------------------------------------------------------------
--
-- 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.
--
--
----------------------------------------------------------------------------------------------------
-- #Script.ReloadScript("scripts/default/entities/player/basicplayer.lua")
DeadBody =
{
type = "DeadBody",
temp_ModelName = "",
DeadBodyParams =
{
max_time_step = 0.025,
sleep_speed = 0.025,
damping = 0.3,
freefall_damping = 0.1,
lying_mode_ncolls = 4,
lying_sleep_speed = 0.065,
lying_damping = 1.5,
},
PhysParams =
{
mass = 80,
height = 1.8,
eyeheight = 1.7,
sphereheight = 1.2,
radius = 0.45,
stiffness_scale = 0,
lod = 1,
retain_joint_vel = 0,
},
Properties =
{
soclasses_SmartObjectClass = "",
bResting = 1,
object_Model = "objects/characters/human/sdk_player/sdk_player.cdf",
lying_damping = 1.5,
bCollidesWithPlayers = 0,
bPushableByPlayers = 0,
Mass = 80,
Stiffness = 0,
MaxTimeStep = 0.025,
bExtraStiff = 0,
bNoFriendlyFire = 0,
PoseAnim = "",
Buoyancy=
{
water_density = 1000,
water_damping = 0,
water_resistance = 1000,
},
TacticalInfo =
{
bScannable = 0,
LookupName = "",
},
},
Editor =
{
Icon = "DeadBody.bmp",
IconOnTop = 1,
},
}
-------------------------------------------------------
function DeadBody:OnLoad(table)
self.temp_ModelName = table.temp_ModelName
self.PhysParams = table.PhysParams
self.DeadBodyParams = table.DeadBodyParams
end
-------------------------------------------------------
function DeadBody:OnSave(table)
table.temp_ModelName = self.temp_ModelName
table.PhysParams = self.PhysParams
table.DeadBodyParams = self.DeadBodyParams
end
-----------------------------------------------------------------------------------------------------------
function DeadBody:OnReset()
--self.temp_ModelName ="";
--self:OnPropertyChange();
self.bScannable = self.Properties.TacticalInfo.bScannable;
-- no problem in repeatedly registering or unregistering
if (self.bScannable==1) then
Game.AddTacticalEntity(self.id, eTacticalEntity_Story);
else
Game.RemoveTacticalEntity(self.id, eTacticalEntity_Story);
end
self:LoadCharacter(0,self.Properties.object_Model);
--self:StartAnimation( 0,"cidle" );
self:PhysicalizeThis();
end
-----------------------------------------------------------------------------------------------------------
function DeadBody:Server_OnInit()
if (not CryAction.IsServer()) then
DeadBody.OnPropertyChange( self );
end
end
-----------------------------------------------------------------------------------------------------------
function DeadBody:Client_OnInit()
DeadBody.OnPropertyChange( self );
self:SetUpdatePolicy( ENTITY_UPDATE_PHYSICS_VISIBLE );
--self:Activate(1);
-- self:RenderShadow( 1 ); -- enable rendering of player shadow
-- self:SetShaderFloat("HeatIntensity",0,0,0);
end
-----------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------
function DeadBody:Server_OnDamageDead( hit )
--printf("server on Damage DEAD %.2f %.2f",hit.impact_force_mul_final,hit.impact_force_mul);
--System.Log("DeadBody hit part "..hit.ipart);
if( hit.ipart ) then
self:AddImpulse( hit.ipart, hit.pos, hit.dir, hit.impact_force_mul );
else
self:AddImpulse( -1, hit.pos, hit.dir, hit.impact_force_mul );
end
end
-----------------------------------------------------------------------------------------------------------
function DeadBody:OnHit()
BroadcastEvent( self,"Hit" );
end
-----------------------------------------------------------------------------------------------------------
function DeadBody:OnPropertyChange()
--System.LogToConsole("prev:"..self.temp_ModelName.." new:"..self.Properties.object_Model);
self.PhysParams.mass = self.Properties.Mass;
if (self.Properties.object_Model ~= self.temp_ModelName) then
self.temp_ModelName = self.Properties.object_Model;
self:LoadCharacter(0,self.Properties.object_Model);
end
self:PhysicalizeThis();
end
--------------------------------------------------------------------------------------------------------
function DeadBody:PhysicalizeThis()
local Properties = self.Properties;
local status = 1;
self.PhysParams.retain_joint_vel = 0;
if (Properties.PoseAnim ~= "") then
self:StartAnimation( 0, Properties.PoseAnim, 0,0,1,1,1,0,1 );
self.PhysParams.retain_joint_vel = 1; --this is just to retain the positions of non-physical bones
end
local bPushableByPlayers = Properties.bPushableByPlayers;
local bCollidesWithPlayers = Properties.bCollidesWithPlayers;
if (status == 1) then
bPushableByPlayers = 0;
bCollidesWithPlayers = 0;
end
self.PhysParams.mass = Properties.Mass;
self.PhysParams.stiffness_scale = Properties.Stiffness*(1-Properties.bExtraStiff*2);
self:Physicalize( 0, PE_ARTICULATED, self.PhysParams );
self:SetPhysicParams(PHYSICPARAM_SIMULATION, self.Properties );
self:SetPhysicParams(PHYSICPARAM_BUOYANCY, self.Properties.Buoyancy );
if (Properties.lying_damping) then
self.DeadBodyParams.lying_damping = Properties.lying_damping;
end
self.DeadBodyParams.max_time_step = Properties.MaxTimeStep;
self:SetPhysicParams(PHYSICPARAM_SIMULATION, self.DeadBodyParams);
self:SetPhysicParams(PHYSICPARAM_ARTICULATED, self.DeadBodyParams);
local flagstab = { flags_mask=geom_colltype_player, flags=geom_colltype_player*bCollidesWithPlayers };
if (status == 1) then
flagstab.flags_mask = geom_colltype_explosion + geom_colltype_ray + geom_colltype_foliage_proxy + geom_colltype_player;
end
self:SetPhysicParams(PHYSICPARAM_PART_FLAGS, flagstab);
flagstab.flags_mask = pef_pushable_by_players;
flagstab.flags = pef_pushable_by_players*bPushableByPlayers;
self:SetPhysicParams(PHYSICPARAM_FLAGS, flagstab);
if (Properties.bResting == 1) then
self:AwakePhysics(0);
else
self:AwakePhysics(1);
end
self:EnableProceduralFacialAnimation(false);
self:PlayFacialAnimation("death_pose_0"..random(1,5), true);
-- small hack: we need one update to sync physics and animation, so here it is after physicalization
-- (our OnUpdate function should just deactivate immediately.)
--self:Activate(1);
end
--function DeadBody:OnUpdate()
--self:Activate(0);
--end
function DeadBody:Event_Hide()
self:Hide(1);
end;
------------------------------------------------------------------------------------------------------
function DeadBody:Event_UnHide()
self:Hide(0);
end;
--------------------------------------------------------------------------------------------------------
function DeadBody:Event_Awake()
self:AwakePhysics(1);
end
--------------------------------------------------------------------------------------------------------
function DeadBody:Event_Hit(sender)
BroadcastEvent(self, "Hit");
end
--------------------------------------------------------------------------------------------------------
DeadBody.Server =
{
OnInit = DeadBody.Server_OnInit,
-- OnShutDown = function( self ) end,
OnDamage = DeadBody.Server_OnDamageDead,
OnHit = DeadBody.OnHit,
OnUpdate=DeadBody.OnUpdate,
}
--------------------------------------------------------------------------------------------------------
DeadBody.Client =
{
OnInit = DeadBody.Client_OnInit,
-- OnShutDown = DeadBody.Client_OnShutDown,
OnDamage=DeadBody.Client_OnDamage,
OnUpdate=DeadBody.OnUpdate,
}
----------------------------------------------------------------------------------------------------
function DeadBody:HasBeenScanned()
self:ActivateOutput("Scanned", true);
end
--------------------------------------------------------------------
DeadBody.FlowEvents =
{
Inputs =
{
Awake = { DeadBody.Event_Awake, "bool" },
Hide = { DeadBody.Event_Hide, "bool" },
UnHide = { DeadBody.Event_UnHide, "bool" },
},
Outputs =
{
Awake = "bool",
Hit = "bool",
Scanned = "bool",
},
}
@@ -1,120 +0,0 @@
----------------------------------------------------------------------------------------------------
--
-- 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.
--
--
----------------------------------------------------------------------------------------------------
-- Zero Gravity entity
GravityBox =
{
Properties =
{
bActive = 1,
BoxMin = { x=-10,y=-10,z=-10 },
BoxMax = { x=10,y=10,z=10 },
bUniform = 1,
Gravity = { x=0,y=0,z=0 },
FalloffInner = 0,
},
Editor =
{
Icon = "GravitySphere.bmp",
},
_PhysTable = { Area={}, },
}
-------------------------------------------------------
function GravityBox:OnLoad(table)
self.bActive = table.bActive
if (self.bActive == 1) then
self:PhysicalizeThis();
else
self:DestroyPhysics();
end
end
-------------------------------------------------------
function GravityBox:OnSave(table)
table.bActive = self.bActive
end
------------------------------------------------------------------------------------------------------
function GravityBox:OnInit()
self.bActive = self.Properties.bActive;
if (self.bActive == 1) then
self:PhysicalizeThis();
end
end
------------------------------------------------------------------------------------------------------
-- OnPropertyChange called only by the editor.
------------------------------------------------------------------------------------------------------
function GravityBox:OnPropertyChange()
if (self.bActive ~= self.Properties.bActive) then
self.bActive = self.Properties.bActive;
if (self.bActive == 1) then
self:PhysicalizeThis();
else
self:DestroyPhysics();
end
end
end
------------------------------------------------------------------------------------------------------
-- OnReset called only by the editor.
------------------------------------------------------------------------------------------------------
function GravityBox:OnReset()
end
------------------------------------------------------------------------------------------------------
function GravityBox:PhysicalizeThis()
if (self.bActive == 1) then
local Properties = self.Properties;
local Area = self._PhysTable.Area;
Area.type = AREA_BOX;
Area.box_min = Properties.BoxMin;
Area.box_max = Properties.BoxMax;
Area.uniform = Properties.bUniform;
Area.falloffInner = Properties.FalloffInner;
Area.gravity = Properties.Gravity;
self:Physicalize( 0,PE_AREA,self._PhysTable );
end
end
------------------------------------------------------------------------------------------------------
function GravityBox:Event_Activate()
if (self.bActive ~= 1) then
self.bActive = 1;
self:PhysicalizeThis();
end
end
------------------------------------------------------------------------------------------------------
function GravityBox:Event_Deactivate()
if (self.bActive ~= 0) then
self.bActive = 0;
self:PhysicalizeThis();
end
end
GravityBox.FlowEvents =
{
Inputs =
{
Deactivate = { GravityBox.Event_Deactivate, "bool" },
Activate = { GravityBox.Event_Activate, "bool" },
},
Outputs =
{
Deactivate = "bool",
Activate = "bool",
},
}
@@ -1,131 +0,0 @@
----------------------------------------------------------------------------------------------------
--
-- 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.
--
--
----------------------------------------------------------------------------------------------------
-- Zero Gravity entity
GravitySphere =
{
Properties =
{
bActive = 1,
Radius = 10,
bUniform = 1,
bEllipsoidal = 1,
FalloffInner = 0,
Gravity = { x=0,y=0,z=0 },
Damping = 0,
},
_PhysTable = { Area={}, },
Editor =
{
Icon = "GravitySphere.bmp",
IconOnTop = 0,
},
}
-------------------------------------------------------
function GravitySphere:OnLoad(table)
self.bActive = table.bActive
self:PhysicalizeThis();
end
-------------------------------------------------------
function GravitySphere:OnSave(table)
table.bActive = self.bActive
end
------------------------------------------------------------------------------------------------------
function GravitySphere:OnInit()
self:OnReset();
end
------------------------------------------------------------------------------------------------------
-- OnPropertyChange called only by the editor.
------------------------------------------------------------------------------------------------------
function GravitySphere:OnPropertyChange()
self:DestroyPhysics();
self.bActive = self.Properties.bActive;
if (self.bActive ~= 0) then
self:PhysicalizeThis();
end
end
------------------------------------------------------------------------------------------------------
-- OnReset called only by the editor.
------------------------------------------------------------------------------------------------------
function GravitySphere:OnReset()
self.bActive = self.Properties.bActive;
self:PhysicalizeThis();
end
------------------------------------------------------------------------------------------------------
function GravitySphere:PhysicalizeThis()
--Log("GravitySphere:PhysicalizeThis");
if (self.bActive == 1) then
local Properties = self.Properties;
local Area = self._PhysTable.Area;
if (Properties.bEllipsoidal ~= 0) then
Area.type = AREA_SPHERE;
else
Area.type = AREA_BOX;
Area.box_min = {x = -Properties.Radius, y = -Properties.Radius, z = -Properties.Radius};
Area.box_max = {x = Properties.Radius, y = Properties.Radius, z = Properties.Radius};
end
Area.radius = Properties.Radius;
Area.uniform = Properties.bUniform;
Area.falloffInner = Properties.FalloffInner;
Area.gravity = Properties.Gravity;
Area.damping = Properties.Damping;
self:Physicalize( 0,PE_AREA,self._PhysTable );
self:SetPhysicParams(PHYSICPARAM_FOREIGNDATA,{foreignData = ZEROG_AREA_ID});
else
self:DestroyPhysics();
end
end
------------------------------------------------------------------------------------------------------
function GravitySphere:Event_Activate()
if (self.bActive ~= 1) then
self.bActive = 1;
self:PhysicalizeThis();
BroadcastEvent(self, "Activate");
end
end
------------------------------------------------------------------------------------------------------
function GravitySphere:Event_Deactivate()
if (self.bActive ~= 0) then
self.bActive = 0;
self:PhysicalizeThis();
BroadcastEvent(self, "Deactivate");
end
end
GravitySphere.FlowEvents =
{
Inputs =
{
Deactivate = { GravitySphere.Event_Deactivate, "bool" },
Activate = { GravitySphere.Event_Activate, "bool" },
},
Outputs =
{
Deactivate = "bool",
Activate = "bool",
},
}
@@ -1,239 +0,0 @@
----------------------------------------------------------------------------------------------------
--
-- 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.
--
--
----------------------------------------------------------------------------------------------------
GravityValve =
{
Properties =
{
bActive = 1,
Strength = 10,
Radius = 10,
bSpline = 0,
},
Server = {},
Client = {},
_PhysTableCyl = { Area={}, },
_PhysTableSph = { Area={}, },
_PhysTableSpl = { Area={points={},}, },
_Points = {},
_Caps = {},
Editor =
{
Icon = "GravitySphere.bmp",
ShowBounds = 1,
},
}
-------------------------------------------------------
function GravityValve:OnLoad(table)
self.bActive = table.bActive
self._Points = table._Points
self._Caps = table._Caps
end
-------------------------------------------------------
function GravityValve:OnSave(table)
table.bActive = self.bActive
table._Points = self._Points
table._Caps = self._Caps
end
function GravityValve:OnSpawn()
self:SetActive( self.Properties.bActive )
end
function GravityValve:OnDestroy()
local Caps = self._Caps
while table.getn(Caps)>0 do
System.RemoveEntity( Caps[1] )
table.remove( Caps, 1 )
end
end
-- OnPropertyChange called only by the editor
function GravityValve:OnPropertyChange()
self:NeedSetup()
end
function GravityValve:OnReset()
self:NeedSetup()
end
function GravityValve:FillPoints()
local MAX_POINTS = 50
local prefix = self:GetName().."_p"
local name
local nPoints = 1
local Points = self._Points
Points[1] = self
for i=1,MAX_POINTS do
name = prefix..tostring(i)
local ent = System.GetEntityByName( name )
if not ent then break end
Points[i+1] = ent
nPoints = i+1
Log("npoints "..nPoints);
end
while table.getn(Points)>nPoints do
Log("removed");
table.remove(Points)
end
for i=1, table.getn(Points) do
Log(".. "..Points[i]:GetName())
end
end
function GravityValve:CreateCylinderArea( from, to, radius, strength )
local Area = self._PhysTableCyl.Area
local axis = DifferenceVectors( to, from )
Area.type = AREA_CYLINDER
Area.radius = radius
Area.height = LengthVector( axis ) * .5
Area.center = ScaleVector( SumVectors( to, from ), 0.5 )
Area.axis = NormalizeVector( axis )
Area.gravity = ScaleVector( Area.axis, strength )
Area.uniform = 1
Area.falloff = 0
return Area
end
function GravityValve:CreateSphereArea( radius, gravity )
local Area = self._PhysTableSph.Area
Area.type = AREA_SPHERE
Area.radius = radius
Area.uniform = 1
Area.falloff = 0
Area.gravity = ScaleVector( gravity, 8 )
return Area
end
function GravityValve:NeedSetup()
self.bNeedSetup = 1
self:Activate(1)
end
function GravityValve:OnChange( index )
self:NeedSetup()
end
function GravityValve:OnUpdate()
--Log("GV:OU "..self:GetName())
if self.bNeedSetup then
local wasActive = self.bActive
self:SetActive(0)
self:SetActive(wasActive)
self.bNeedSetup = nil
self:Activate(0)
end
end
GravityValve.Server.OnUpdate = GravityValve.OnUpdate
GravityValve.Client.OnUpdate = GravityValve.OnUpdate
function GravityValve:SetActive( bActive )
if bActive == self.bActive then return end
self:FillPoints()
local p, n
local Points = self._Points
local Caps = self._Caps
n = table.getn(Points)
--Log("GravityValve:SetActive "..tostring(bActive).." on valve "..self:GetName())
if bActive == 1 then
if (self.Properties.bSpline == 1) then
local Area = self._PhysTableSpl.Area;
local splinePoints = self._PhysTableSpl.Area.points;
for p = 1, n do
splinePoints[p] = {x=0,y=0,z=0};
Points[p]:GetWorldPos(splinePoints[p]);
--Log("Gravity Stream point "..p..":"..Vec2Str(splinePoints[p]));
end
Area.type = AREA_SPLINE;
Area.radius = self.Properties.Radius;
--Area.uniform = 1;
Area.falloff = 0;
Area.gravity = {x=0,y=0,z=self.Properties.Strength};
Area.damping = 2.0;
self:Physicalize(0, PE_AREA, self._PhysTableSpl);
self:SetPhysicParams(PHYSICPARAM_FOREIGNDATA,{foreignData = ZEROG_AREA_ID});
else
local params = {}
params.class = "GravityStreamCap"
params.orientation = {x=1,y=0,z=0}
for p = 2, n do
self:CreateCylinderArea( Points[p-1]:GetPos(), Points[p]:GetPos(), self.Properties.Radius, self.Properties.Strength )
Points[p]:Physicalize(0, PE_AREA, self._PhysTableCyl)
Points[p]:SetPhysicParams(PHYSICPARAM_FOREIGNDATA,{foreignData = ZEROG_AREA_ID});
if p > 2 then
params.position = Points[p-1]:GetPos()
local ent = System.SpawnEntity( params )
table.insert( Caps, ent.id )
self:CreateSphereArea( self.Properties.Radius, self._PhysTableCyl.Area.gravity )
ent:Physicalize(0, PE_AREA, self._PhysTableSph)
ent:SetPhysicParams(PHYSICPARAM_FOREIGNDATA,{foreignData = ZEROG_AREA_ID});
end
end
end
elseif bActive == 0 and self.bActive then
self:DestroyPhysics();
for p = 2, n do
Points[p]:DestroyPhysics()
end
self:OnDestroy()
end
self.bActive = bActive
end
function GravityValve:Event_Enable()
--Log("GravityValve: GetEnable")
self:SetActive(1)
end
function GravityValve:Event_Disable()
--Log("GravityValve: GetDisable")
self:SetActive(0)
end
GravityValve.FlowEvents =
{
Inputs =
{
Disable = { GravityValve.Event_Disable, "bool" },
Enable = { GravityValve.Event_Enable, "bool" },
},
Outputs =
{
Disable = "bool",
Enable = "bool",
},
}
@@ -1,77 +0,0 @@
----------------------------------------------------------------------------------------------------
--
-- 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.
--
--
----------------------------------------------------------------------------------------------------
ParticlePhysics =
{
Properties =
{
object_Model = "Objects/default/primitive_box.cgf",
Particle =
{
mass = 50.0,
radius = 1.0,
air_resistance = 0.0,
gravity = {x=0.0, y=0.0, z=-9.81},
water_resistance = 0.5,
water_gravity = {x=0.0, y=0.0, z=-9.81*0.8},
min_bounce_vel = 1.5,
accel_thrust = 0,
accel_lift = 0,
velocity = {x=0.0, y=0.0, z=0.0},
thickness = 1.0,
wspin = {x=0.0, y=0.0, z=0.0},
normal = {x=0.0, y=0.0, z=1.0},
pierceability = 15,
constant_orientation = false,
single_contact = true,
no_roll = false,
no_spin = true,
no_path_alignment = false,
collider_to_ignore = 0,
material = "", -- this is supposed to be the surface type
},
},
Editor =
{
Icon = "physicsobject.bmp",
IconOnTop = 1,
},
}
function ParticlePhysics:SetFromProperties()
local Properties = self.Properties;
self:FreeSlot(0);
if (Properties.object_Model ~= "") then
self:LoadObject(0, Properties.object_Model);
end
NormalizeVector(Properties.Particle.normal);
self:Physicalize(0, PE_PARTICLE, Properties);
self:SetSlotPos(0, {0.0, 0.0, -Properties.Particle.thickness*0.5});
end
function ParticlePhysics:OnSpawn()
self:OnReset();
end
function ParticlePhysics:OnPropertyChange()
self:OnReset();
end
function ParticlePhysics:OnReset()
self:SetFromProperties();
end
@@ -1,188 +0,0 @@
----------------------------------------------------------------------------------------------------
--
-- 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.
--
--
----------------------------------------------------------------------------------------------------
Wind = {
type = "WindController",
Properties = {
vVelocity={x=1.0,y=0.0,z=0.0},
fFadeTime = 1,--used only when the fog is triggered manually, with activate/deactivate events.
},
Editor={
Icon="Tornado.bmp",
},
}
function Wind:OnInit()
self.oldVelocity = {x=0.0,y=0.0,z=0.0};
self.occupied = 0;
self.lasttime = 0;
self:OnReset();
self:RegisterForAreaEvents(1);
end
function Wind:OnPropertyChange()
self:OnReset();
end
function Wind:OnReset()
self:RegisterForAreaEvents(1);
end
function Wind:OnSave(tbl)
tbl.bTriggered = self.bTriggered
tbl.oldVelocity = self.oldVelocity
tbl.fadeamt = self.fadeamt
tbl.Who = self.Who
end
function Wind:OnLoad(tbl)
self.bTriggered = tbl.bTriggered
self.oldVelocity = tbl.oldVelocity
self.fadamt = tbl.fadeamt
self.Who = tbl.Who
end
-----------------------------------------------------------------------------
-- fade: 0-out 1-in
function Wind:OnProceedFadeArea( player,areaId,fadeCoeff )
self:Fade(fadeCoeff);
end
function Wind:ResetValues()
System.SetWind(self.oldVelocity);
end
-----------------------------------------------------------------------------
function Wind:OnEnterArea( player,areaId )
if((player and (not player.actor:IsPlayer())) or self.occupied == 1) then
return
end
self.oldVelocity = System.GetWind();
self.occupied = 1;
end
-----------------------------------------------------------------------------
function Wind:OnLeaveArea( player,areaId )
if(player and (not player.actor:IsPlayer())) then
return
end
self:ResetValues();
self.occupied = 0;
end
-----------------------------------------------------------------------------
function Wind:OnShutDown()
self:RegisterForAreaEvents(0);
end
function Wind:Event_Enable( sender )
if(self.occupied == 0 ) then
if (self.fadeamt and self.fadeamt<1) then
self:ResetValues();
end
self:OnEnterArea( );
self.fadeamt = 0;
self.lasttime = _time;
self.exitfrom = nil;
end
self:SetTimer(0, 1);
BroadcastEvent( self,"Enable" );
end
function Wind:Event_Disable( sender )
if(self.occupied == 1 ) then
--self:OnLeaveArea( );
self.occupied = 0;
self.fadeamt = 0;
self.lasttime = _time;
self.exitfrom = 1;
end
self:SetTimer(0, 1);
BroadcastEvent( self,"Disable" );
end
function Wind:OnTimer()
--System.Log("Ontimer ");
self:SetTimer(0, 1);
if (self.fadeamt) then
local delta = _time - self.lasttime;
self.lasttime = _time;
self.fadeamt = self.fadeamt + (delta / self.Properties.fFadeTime);
if (self.fadeamt>=1) then
self.fadeamt = 1;
self:KillTimer(0);
end
----------------------------------------------
--fade
local fadeCoeff = self.fadeamt;
if (self.exitfrom) then
fadeCoeff = 1 - fadeCoeff;
end
fadeCoeff = math.sqrt( fadeCoeff );
fadeCoeff = math.sqrt( fadeCoeff );
self:Fade(fadeCoeff);
--self:OnProceedFadeArea( nil,0,self.fadeamt );
else
self:KillTimer(0);
end
end
function Wind:Fade(fadeCoeff)
System.SetWind(LerpColors(self.oldVelocity, self.Properties.vVelocity, fadeCoeff));
end
Wind.FlowEvents =
{
Inputs =
{
Disable = { Wind.Event_Disable, "bool" },
Enable = { Wind.Event_Enable, "bool" },
},
Outputs =
{
Disable = "bool",
Enable = "bool",
},
}

Some files were not shown because too many files have changed in this diff Show More