Files
o3de/Gems/LyShine/Code/Source/Particle/UiParticle.cpp
T
Esteban Papp 1f9b284de2 Merge branch 'development' into cmake/SPEC-7179
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>

# Conflicts:
#	Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h
#	Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h
#	Code/Editor/Plugins/EditorCommon/stdafx.cpp
#	Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h
#	Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h
#	Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h
#	Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h
#	Code/Tools/AssetProcessor/native/precompiled.h
#	Code/Tools/Standalone/StandaloneTools_precompiled.h
#	Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h
#	Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h
#	Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h
#	Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake
#	Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h
#	Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h
#	Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp
#	Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake
#	Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h
#	Gems/Blast/Code/Source/StdAfx.cpp
#	Gems/Camera/Code/Source/Camera_precompiled.h
#	Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h
#	Gems/FastNoise/Code/Source/FastNoise_precompiled.h
#	Gems/Gestures/Code/Source/Gestures_precompiled.h
#	Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h
#	Gems/GraphCanvas/Code/precompiled.h
#	Gems/ImGui/Code/Source/ImGui_precompiled.h
#	Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h
#	Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h
#	Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp
#	Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h
#	Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h
#	Gems/LyShine/Code/Source/LyShine_precompiled.h
#	Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h
#	Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h
#	Gems/Maestro/Code/Source/Maestro_precompiled.h
#	Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h
#	Gems/Metastream/Code/Source/Metastream_precompiled.h
#	Gems/Microphone/Code/Source/Microphone_precompiled.h
#	Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h
#	Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h
#	Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h
#	Gems/PhysX/Code/Source/PhysX_precompiled.h
#	Gems/PhysX/Code/physx_unsupported_files.cmake
#	Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h
#	Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h
#	Gems/ScriptCanvas/Code/Editor/precompiled.h
#	Gems/ScriptCanvas/Code/Source/precompiled.h
#	Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h
#	Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h
#	Gems/ScriptEvents/Code/Source/precompiled.h
#	Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp
#	Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h
#	Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h
#	Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h
#	Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h
#	Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h
#	Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h
#	Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h
#	Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h
#	Gems/Twitch/Code/Source/Twitch_precompiled.h
#	Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
2021-07-16 15:42:37 -07:00

228 lines
8.6 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "UiParticle.h"
#include "UiParticleEmitterComponent.h"
#include <LyShine/ISprite.h>
#include <IRenderer.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
void UiParticle::Init(UiParticle::UiParticleInitialParameters* initialParams)
{
m_particleAge = 0.0f;
m_particleLifetime = initialParams->lifetime;
m_emitterInitialOffset = initialParams->initialEmitterOffset;
m_position = initialParams->position;
m_positionDifference = AZ::Vector2::CreateZero();
m_velocity = initialParams->initialVelocity;
m_accelerationBasedVelocity = AZ::Vector2::CreateZero();
m_acceleration = initialParams->acceleration;
m_rotation = initialParams->rotation;
m_angularVelocity = initialParams->angularVelocity;
m_pivot = initialParams->pivot;
m_size = initialParams->size;
m_color = initialParams->color;
m_spriteCellIndex = initialParams->spriteSheetCellIndex;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void UiParticle::Update(float deltaTime, const UiParticleUpdateParameters& updateParameters)
{
AZ::Vector2 previousPosition = m_position;
float velocityStrength = 1.0f;
if (updateParameters.isSpeedMultiplierUsed)
{
float particleLifetimePercentage = (updateParameters.isParticleInfinite ? 0.0f : m_particleAge / m_particleLifetime);
updateParameters.speedMultiplier->GetValue(particleLifetimePercentage, velocityStrength);
}
AZ::Vector2 currentVelocity = m_velocity * velocityStrength;
if (updateParameters.isVelocityCartesian)
{
m_position += currentVelocity * deltaTime;
}
else
{
AZ::Vector2 offset = m_position - m_emitterInitialOffset;
float radius = AZ::GetMax<float>(offset.GetLength(), 0.1f);
float newRadius = radius + currentVelocity.GetX() * deltaTime;
if (newRadius > 0.0f)
{
offset = (offset / radius) * newRadius;
float angle = (currentVelocity.GetY() * deltaTime) / newRadius;
m_position.SetX(offset.GetX() * cos(angle) + offset.GetY() * sin(angle));
m_position.SetY((-offset.GetX()) * sin(angle) + offset.GetY() * cos(angle));
m_position += m_emitterInitialOffset;
}
else
{
m_position = m_emitterInitialOffset;
}
}
if (updateParameters.isAccelerationCartesian)
{
m_position += m_accelerationBasedVelocity * deltaTime;
m_position += 0.5f * deltaTime * deltaTime * m_acceleration;
}
else
{
AZ::Vector2 offset = m_position - m_emitterInitialOffset;
float radius = AZ::GetMax<float>(offset.GetLength(), 0.1f);
float newRadius = radius + m_accelerationBasedVelocity.GetX() * deltaTime;
if (newRadius > 0.0f)
{
offset = (offset / radius) * newRadius;
float angle = (m_accelerationBasedVelocity.GetY() * deltaTime) / newRadius;
m_position.SetX(offset.GetX() * cos(angle) + offset.GetY() * sin(angle));
m_position.SetY((-offset.GetX()) * sin(angle) + offset.GetY() * cos(angle));
m_position += m_emitterInitialOffset;
}
else
{
m_position = m_emitterInitialOffset;
}
}
m_positionDifference = m_position - previousPosition;
m_accelerationBasedVelocity += m_acceleration * deltaTime;
m_rotation += m_angularVelocity * deltaTime;
m_particleAge += deltaTime;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool UiParticle::FillVertices(SVF_P2F_C4B_T2F_F4B* outputVertices, const UiParticleRenderParameters& renderParameters, const AZ::Matrix4x4& transform)
{
float particleLifetimePercentage = (renderParameters.isParticleInfinite ? 0.0f : m_particleAge / m_particleLifetime);
float alphaStrength = 1.0f;
AZ::Color currentColor = m_color;
if (renderParameters.isColorOverrideUsed)
{
currentColor = renderParameters.colorOverride;
}
if (renderParameters.isAlphaOverrideUsed)
{
currentColor.SetA(renderParameters.alphaOverride);
}
if (renderParameters.isAlphaMultiplierUsed)
{
renderParameters.alphaMultiplier->GetValue(particleLifetimePercentage, alphaStrength);
}
AZ::u8 currentAlpha = static_cast<AZ::u8>(currentColor.GetA8() * alphaStrength * renderParameters.alphaFadeMultiplier);
if (currentAlpha == 0)
{
return false;
}
int currentIndex = m_spriteCellIndex;
if (renderParameters.spritesheetCellIndexAnimated)
{
int unwrappedIndex = m_spriteCellIndex + static_cast<int>(m_particleAge / renderParameters.spritesheetFrameDelay);
int clampedIndex = unwrappedIndex - renderParameters.spritesheetStartFrame;
if (!renderParameters.spritesheetCellIndexAnimationLooped)
{
clampedIndex = AZ::GetClamp<int>(clampedIndex, 0, renderParameters.spritesheetFrameRange);
}
int rangeIncludingEndFrame = renderParameters.spritesheetFrameRange + 1;
currentIndex = renderParameters.spritesheetStartFrame + (clampedIndex % rangeIncludingEndFrame);
}
const UiTransformInterface::RectPoints& uvCoords = (renderParameters.sprite ? renderParameters.sprite->GetCellUvCoords(currentIndex) : UiTransformInterface::RectPoints(0, 1, 0, 1));
const AZ::Vector2 uvs[4] =
{
uvCoords.TopLeft(),
uvCoords.TopRight(),
uvCoords.BottomRight(),
uvCoords.BottomLeft(),
};
float widthMultiplier = 1.0f;
float heightMultiplier = 1.0f;
if (renderParameters.isWidthMultiplierUsed)
{
renderParameters.sizeWidthMultiplier->GetValue(particleLifetimePercentage, widthMultiplier);
}
if (renderParameters.isAspectRatioLocked)
{
heightMultiplier = widthMultiplier;
}
else if (renderParameters.isHeightMultiplierUsed)
{
renderParameters.sizeHeightMultiplier->GetValue(particleLifetimePercentage, heightMultiplier);
}
AZ::Color colorStrength(1.0f, 1.0f, 1.0f, 1.0f);
if (renderParameters.isColorMultiplierUsed)
{
renderParameters.colorMultiplier->GetValue(particleLifetimePercentage, colorStrength);
}
currentColor = currentColor * colorStrength;
uint32 packedColor = (currentAlpha << 24) | (currentColor.GetR8() << 16) | (currentColor.GetG8() << 8) | currentColor.GetB8();
AZ::Vector2 unitQuadQuarters[4];
unitQuadQuarters[0].Set(0.0f - m_pivot.GetX(), 0.0f - m_pivot.GetY());
unitQuadQuarters[1].Set(1.0f - m_pivot.GetX(), 0.0f - m_pivot.GetY());
unitQuadQuarters[2].Set(1.0f - m_pivot.GetX(), 1.0f - m_pivot.GetY());
unitQuadQuarters[3].Set(0.0f - m_pivot.GetX(), 1.0f - m_pivot.GetY());
float sinRotation = sin(m_rotation);
float cosRotation = cos(m_rotation);
AZ::Vector2 particleDirectionVectors[2];
if (renderParameters.isRotationVelocityBased)
{
particleDirectionVectors[1] = m_positionDifference.GetNormalizedSafe() * -1.0f;
particleDirectionVectors[0] = particleDirectionVectors[1].GetPerpendicular() * -1.0f;
}
else
{
particleDirectionVectors[0].Set(cosRotation, sinRotation);
particleDirectionVectors[1].Set(-sinRotation, cosRotation);
}
AZ::Vector2 particlePosition = m_position;
if (renderParameters.isRelativeToEmitter)
{
particlePosition += (*renderParameters.particleOffset) - m_emitterInitialOffset;
}
const int verticesPerParticle = 4;
for (int i = 0; i < verticesPerParticle; ++i)
{
AZ::Vector2 cornerVector = particlePosition + (unitQuadQuarters[i].GetX() * particleDirectionVectors[0] * m_size.GetX() * widthMultiplier) + (unitQuadQuarters[i].GetY() * particleDirectionVectors[1] * m_size.GetY() * heightMultiplier);
AZ::Vector3 point3(cornerVector.GetX(), cornerVector.GetY(), 1.0f);
point3 = transform * point3;
outputVertices[i].xy = Vec2(point3.GetX(), point3.GetY());
outputVertices[i].color.dcolor = packedColor;
outputVertices[i].st = Vec2(uvs[i].GetX(), uvs[i].GetY());
outputVertices[i].texIndex = 0;
outputVertices[i].texHasColorChannel = 1;
outputVertices[i].texIndex2 = 0;
outputVertices[i].pad = 0;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool UiParticle::IsActive(bool infiniteLifetime) const
{
return (m_particleAge < m_particleLifetime || infiniteLifetime);
}