1f9b284de2
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
164 lines
6.9 KiB
C++
164 lines
6.9 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 "ScriptEventDefinition.h"
|
|
#include "ScriptEventsBus.h"
|
|
|
|
#include <AzCore/std/string/regex.h>
|
|
|
|
namespace ScriptEvents
|
|
{
|
|
void ScriptEvent::RegisterInternal()
|
|
{
|
|
// Register the bus with the system component
|
|
ScriptEventBus::Broadcast(&ScriptEventRequests::RegisterScriptEventFromDefinition, *this);
|
|
}
|
|
|
|
void ScriptEvent::Register(AZ::ScriptDataContext&)
|
|
{
|
|
RegisterInternal();
|
|
}
|
|
|
|
void ScriptEvent::Release(AZ::ScriptDataContext&)
|
|
{
|
|
}
|
|
|
|
void ScriptEvent::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
|
{
|
|
serializeContext->Class<ScriptEvent>()
|
|
->Version(1)
|
|
->Field("m_version", &ScriptEvent::m_version)
|
|
->Field("m_name", &ScriptEvent::m_name)
|
|
->Field("m_category", &ScriptEvent::m_category)
|
|
->Field("m_tooltip", &ScriptEvent::m_tooltip)
|
|
->Field("m_addressType", &ScriptEvent::m_addressType)
|
|
->Field("m_methods", &ScriptEvent::m_methods)
|
|
;
|
|
|
|
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
|
{
|
|
editContext->Class<ScriptEvent>("Script Event Definition", "Data driven script event definition")
|
|
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
|
->Attribute(AZ::Edit::Attributes::ChildNameLabelOverride, &ScriptEvent::GetLabel)
|
|
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
|
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptEvent::m_name, "Name", "Name of the Script Event")
|
|
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptEvent::m_tooltip, "Tooltip", "The name of this Script Event")
|
|
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptEvent::m_category, "Category", "The category that the Event will be put into")
|
|
->DataElement(AZ::Edit::UIHandlers::ComboBox, &ScriptEvent::m_addressType, "Address Type", "If required, this defines the address type for this event")
|
|
->Attribute(AZ::Edit::Attributes::GenericValueList, &Types::GetValidAddressTypes)
|
|
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptEvent::m_methods, "Events", "The list of events available.")
|
|
;
|
|
}
|
|
}
|
|
|
|
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
|
{
|
|
behaviorContext->Class<ScriptEvent>("ScriptEvent")
|
|
->Constructor<AZ::ScriptDataContext&>()
|
|
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
|
->Method("AddMethod", &ScriptEvent::AddMethod)
|
|
->Method("Register", &ScriptEvent::Register)
|
|
->Property("Name", BehaviorValueProperty(&ScriptEvent::m_name))
|
|
->Property("AddressType", BehaviorValueProperty(&ScriptEvent::m_addressType))
|
|
->Property("Events", BehaviorValueProperty(&ScriptEvent::m_methods))
|
|
;
|
|
}
|
|
}
|
|
|
|
AZ::Outcome<bool, AZStd::string> ScriptEvent::Validate() const
|
|
{
|
|
const AZStd::string& name = GetName();
|
|
const AZ::Uuid& addressType = GetAddressType();
|
|
|
|
AZ::BehaviorContext* behaviorContext = nullptr;
|
|
AZ::ComponentApplicationBus::BroadcastResult(behaviorContext, &AZ::ComponentApplicationBus::Events::GetBehaviorContext);
|
|
AZ_Assert(behaviorContext, "A valid Behavior Context is expected");
|
|
|
|
if (m_version == 0 && behaviorContext->m_ebuses.find(name.c_str()) != behaviorContext->m_ebuses.end())
|
|
{
|
|
// An EBus with the same name already is registered, this is not allowed.
|
|
return AZ::Failure(AZStd::string::format("A Script Event with the name \"%s\" already exist, consider renaming this Script Event as duplicate names are not supported", name.c_str()));
|
|
}
|
|
|
|
// Validate address type
|
|
if (!Types::ValidateAddressType(addressType))
|
|
{
|
|
return AZ::Failure(AZStd::string::format("The specified type %s is not valid as an address for Script Events: %s", addressType.ToString<AZStd::string>().c_str(), name.c_str()));
|
|
}
|
|
|
|
// Definition name cannot be empty
|
|
if (name.empty())
|
|
{
|
|
return AZ::Failure(AZStd::string("Event name cannot be empty"));
|
|
}
|
|
|
|
// Name cannot start with a number
|
|
if (isdigit(name.at(0)))
|
|
{
|
|
return AZ::Failure(AZStd::string::format("%s, names cannot start with a number", name.c_str()));
|
|
}
|
|
|
|
AZStd::smatch match;
|
|
|
|
// Ascii-only
|
|
AZStd::regex asciionly_regex("[^\x0A\x0D\x20-\x7E]");
|
|
AZStd::regex_match(name, match, asciionly_regex);
|
|
if (!match.empty())
|
|
{
|
|
return AZ::Failure(AZStd::string::format("%s, invalid name, names may only contain ASCII characters", name.c_str()));
|
|
}
|
|
|
|
// No whitespace
|
|
AZStd::regex nowhitespace_regex("[^\\S]");
|
|
AZStd::regex_match(name, match, nowhitespace_regex);
|
|
if (!match.empty())
|
|
{
|
|
return AZ::Failure(AZStd::string::format("%s, invalid name, event names should not contain white space", name.c_str()));
|
|
}
|
|
|
|
// Conform to valid function names
|
|
AZStd::regex validate_regex("[_[:alpha:]][_[:alnum:]]*");
|
|
AZStd::regex_match(name, match, validate_regex);
|
|
if (match.empty())
|
|
{
|
|
return AZ::Failure(AZStd::string::format("%s, invalid name specified, event name must only have alpha numeric characters, may not start with a number and may not have white space", name.c_str()));
|
|
}
|
|
|
|
if (m_methods.empty())
|
|
{
|
|
return AZ::Failure(AZStd::string::format("Script Events (%s) must provide at least one event otherwise they are unusable, be sure to add an event before saving.", name.c_str()));
|
|
}
|
|
|
|
// Validate each method
|
|
AZStd::string methodName;
|
|
int methodIndex = 0;
|
|
for (const Method& method : m_methods)
|
|
{
|
|
auto outcome = method.Validate();
|
|
if (!outcome.IsSuccess())
|
|
{
|
|
return outcome;
|
|
}
|
|
|
|
if (method.GetName().compare(methodName) == 0)
|
|
{
|
|
return AZ::Failure(AZStd::string::format("Cannot have duplicate method names (%d: %s) make sure each method name is unique", methodIndex, methodName.c_str()));
|
|
}
|
|
|
|
methodName = method.GetName();
|
|
++methodIndex;
|
|
|
|
}
|
|
|
|
return AZ::Success(true);
|
|
}
|
|
|
|
}
|