Browse Source

Added photosensitive seizure warnings.

A new AtomSampleComponent base class is shared by all ASV samples. If any sample needs to warn the user about its content, there is a ContentWarning variable that can be overridden. The SampleComponentManager will display the warning before opening that sample. I also added similar warnings when opening the Script Runner and Pre-Commit Wizard dialogs, because any automation script is likely to cause flashing images.

Note that I also remove the ability to use Ctrl-0 through Ctrl-9 to open samples. It only worked for the first 10 samples, and was useful in the early days of AtomSampleViewer when we couldn’t show ImGui during RHI samples. Now that all samples keep ImGui visible, we can stop maintaining this feature.

Fixes https://github.com/o3de/o3de-atom-sampleviewer/issues/398

Signed-off-by: santorac <[email protected]>
santorac 3 years ago
parent
commit
dbeb75b6c9

+ 14 - 0
Gem/Code/Source/AtomSampleComponent.cpp

@@ -0,0 +1,14 @@
+/*
+ * 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 <AtomSampleComponent.h>
+
+namespace AtomSampleViewer
+{
+
+}

+ 31 - 0
Gem/Code/Source/AtomSampleComponent.h

@@ -0,0 +1,31 @@
+/*
+ * 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
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Component/Component.h>
+
+namespace AtomSampleViewer
+{
+    class AtomSampleComponent
+        : public AZ::Component
+    {
+    public:
+        AZ_RTTI(AtomSampleComponent, "{2318DFD6-BC6B-4335-9F25-8E270A10CA81}", AZ::Component);
+
+        AtomSampleComponent() = default;
+        ~AtomSampleComponent() override = default;
+
+        // Redefine this string in the sample component subclass to provide a sample-specific warning message.
+        // Any non-empty string will automatically cause a warning message to be displayed before opening the sample.
+        static constexpr const char* ContentWarning = "";
+        
+        // This is a common photosensitive/seizure warning that could be used for the above ContentWarning in specific samples as needed.
+        static constexpr const char CommonPhotosensitiveWarning[] = "This sample includes flashing images that could cause seizures or other adverse effects in photosensitive individuals.";
+    };
+} // namespace AtomSampleViewer

+ 3 - 3
Gem/Code/Source/CommonSampleComponentBase.h

@@ -8,7 +8,7 @@
 
 #pragma once
 
-#include <AzCore/Component/Component.h>
+#include <AtomSampleComponent.h>
 #include <AzCore/Component/TransformBus.h>
 #include <AzCore/Component/EntityBus.h>
 #include <AzFramework/Entity/EntityContextBus.h>
@@ -25,12 +25,12 @@
 namespace AtomSampleViewer
 {
     class CommonSampleComponentBase
-        : public AZ::Component
+        : public AtomSampleComponent
         , public AZ::TransformNotificationBus::MultiHandler
         , public AZ::EntityBus::MultiHandler
     {
     public:
-        AZ_TYPE_INFO(CommonSampleComponentBase, "{7EECDF09-B774-46C1-AD6E-060CE5717C05}");
+        AZ_RTTI(CommonSampleComponentBase, "{7EECDF09-B774-46C1-AD6E-060CE5717C05}", AtomSampleComponent);
 
         static void Reflect(AZ::ReflectContext* context);
 

+ 3 - 3
Gem/Code/Source/RHI/BasicRHIComponent.h

@@ -7,7 +7,7 @@
  */
 
 #pragma once
-#include <AzCore/Component/Component.h>
+#include <AtomSampleComponent.h>
 #include <AzCore/std/smart_ptr/shared_ptr.h>
 
 #include <Atom/RPI.Public/Image/StreamingImage.h>
@@ -81,13 +81,13 @@ namespace AtomSampleViewer
     };
 
     class BasicRHIComponent
-        : public AZ::Component
+        : public AtomSampleComponent
         , public AZ::RHI::RHISystemNotificationBus::Handler
     {
         friend class RHISamplePass;
 
     public:
-        AZ_RTTI(BasicRHIComponent, "{FAB340E4-2D91-48CD-A7BC-81ED25721415}", AZ::Component);
+        AZ_RTTI(BasicRHIComponent, "{FAB340E4-2D91-48CD-A7BC-81ED25721415}", AtomSampleComponent);
 
         BasicRHIComponent() = default;
         ~BasicRHIComponent() override = default;

+ 2 - 0
Gem/Code/Source/RHI/MultiViewportSwapchainComponent.h

@@ -30,6 +30,8 @@ namespace AtomSampleViewer
         , public AzFramework::WindowNotificationBus::Handler
     {
     public:
+        static constexpr const char* ContentWarning = CommonPhotosensitiveWarning;
+
         AZ_COMPONENT(MultiViewportSwapchainComponent, "{45118741-F7DB-4EE0-9EBF-59B85D7F6194}", AZ::Component);
         AZ_DISABLE_COPY(MultiViewportSwapchainComponent);
 

+ 2 - 0
Gem/Code/Source/RHI/SwapchainExampleComponent.h

@@ -18,6 +18,8 @@ namespace AtomSampleViewer
         , public AZ::TickBus::Handler
     {
     public:
+        static constexpr const char* ContentWarning = CommonPhotosensitiveWarning;
+
         AZ_COMPONENT(SwapchainExampleComponent, "{F8A990AD-63C0-43D8-AE9B-FB9D84CB58E2}", AZ::Component);
 
         static void Reflect(AZ::ReflectContext* context);

+ 35 - 45
Gem/Code/Source/SampleComponentManager.cpp

@@ -165,6 +165,7 @@ namespace AtomSampleViewer
         entry.m_componentDescriptor = T::CreateDescriptor();
         entry.m_parentMenuName = menuName;
         entry.m_fullName = entry.m_parentMenuName + '/' + entry.m_sampleName;
+        entry.m_contentWarning = T::ContentWarning;
 
         return entry;
     }
@@ -333,8 +334,6 @@ namespace AtomSampleViewer
         m_exampleEntity = aznew AZ::Entity();
 
         m_entityContextId = AzFramework::EntityContextId::CreateNull();
-
-        memset(m_alphanumericNumbersDown, 0, s_alphanumericCount);
     }
 
     SampleComponentManager::~SampleComponentManager()
@@ -556,16 +555,6 @@ namespace AtomSampleViewer
             {
                 screenshotRequest = true;
             }
-
-            for (size_t i = 0; i < m_availableSamples.size(); ++i)
-            {
-                if (m_alphanumericNumbersDown[i] && i < s_alphanumericCount && m_isSampleSupported[i])
-                {
-                    m_sampleChangeRequest = true;
-                    m_selectedSampleIndex = static_cast<int32_t>(i);
-                    break;
-                }
-            }
         }
 
         // Request a frame capture only once per key press, even if the keys are held down for multiple ticks.
@@ -705,14 +694,6 @@ namespace AtomSampleViewer
                 m_escapeDown = true;
             }
 
-            for (size_t i = 0; i < samplesAvailableCount; ++i)
-            {
-                if ((i < s_alphanumericCount) && (inputChannelId == sampleInputMapping[i]))
-                {
-                    m_alphanumericNumbersDown[i] = true;
-                }
-            }
-
             break;
         }
         case AzFramework::InputChannel::State::Ended:
@@ -742,14 +723,6 @@ namespace AtomSampleViewer
                 m_escapeDown = false;
             }
 
-            for (size_t i = 0; i < samplesAvailableCount; ++i)
-            {
-                if ((i < s_alphanumericCount) && (inputChannelId == sampleInputMapping[i]))
-                {
-                    m_alphanumericNumbersDown[i] = false;
-                }
-            }
-
             break;
         }
         default:
@@ -852,6 +825,7 @@ namespace AtomSampleViewer
 
         m_scriptManager->TickImGui();
 
+        m_contentWarningDialog.TickPopup();
     }
 
     void SampleComponentManager::ShowMenuBar()
@@ -928,35 +902,37 @@ namespace AtomSampleViewer
                             SampleEntry& sample = m_availableSamples[index];
                             const char* sampleName = sample.m_sampleName.c_str();
                             bool enabled = m_isSampleSupported[index];
-                            if (index < s_alphanumericCount)
+
+                            if (ImGui::MenuItem(sampleName, nullptr, false, enabled))
                             {
-                                const AZStd::string hotkeyName = AZStd::string::format("Ctrl-%d: ", (index + 1) % 10);
+                                Utils::ReportScriptableAction("OpenSample('%s')", sample.m_sampleName.c_str());
 
-                                if (ImGui::MenuItem(sampleName, hotkeyName.c_str(), false, enabled))
+                                if (sample.m_contentWarning.empty())
                                 {
-                                    m_selectedSampleIndex = index;
                                     m_sampleChangeRequest = true;
+                                    m_selectedSampleIndex = index;
                                 }
-                            }
-                            else
-                            {
-                                if (ImGui::MenuItem(sampleName, nullptr, false, enabled))
+                                else
                                 {
-                                    m_selectedSampleIndex = index;
-                                    m_sampleChangeRequest = true;
+                                    m_contentWarningDialog.OpenPopupConfirmation(
+                                        "Sample Content Warning",
+                                        sample.m_contentWarning,
+                                        [this, index]() {
+                                            m_sampleChangeRequest = true;
+                                            m_selectedSampleIndex = index;
+                                        });
                                 }
+
                             }
+
+
+
                         }
 
                         ImGui::EndMenu();
                     }
                 }
 
-                if (m_sampleChangeRequest)
-                {
-                    Utils::ReportScriptableAction("OpenSample('%s')", m_availableSamples[m_selectedSampleIndex].m_sampleName.c_str());
-                }
-
                 ImGui::EndMenu();
             }
 #ifdef AZ_PROFILE_TELEMETRY
@@ -972,13 +948,27 @@ namespace AtomSampleViewer
 
             if (ImGui::BeginMenu("Automation"))
             {
+                const char* AutomationContentWarningTitle = "Sample Content Warning";
+                const char* AutomationContentWarning = "Running automated scripts will trigger flashing images that could cause seizures or other adverse effects in photosensitive individuals.";
+
                 if (ImGui::MenuItem("Run Script..."))
                 {
-                    m_scriptManager->OpenScriptRunnerDialog();
+                    m_contentWarningDialog.OpenPopupConfirmation(
+                        AutomationContentWarningTitle,
+                        AutomationContentWarning,
+                        [this]() {
+                            m_scriptManager->OpenScriptRunnerDialog();
+                        });
+
                 }
                 if (ImGui::MenuItem("Run Precommit Wizard..."))
                 {
-                    m_scriptManager->OpenPrecommitWizard();
+                    m_contentWarningDialog.OpenPopupConfirmation(
+                        AutomationContentWarningTitle,
+                        AutomationContentWarning,
+                        [this]() {
+                            m_scriptManager->OpenPrecommitWizard();
+                        });
                 }
 
                 ImGui::EndMenu();

+ 4 - 4
Gem/Code/Source/SampleComponentManager.h

@@ -40,6 +40,7 @@
 
 #include <Utils/ImGuiSaveFilePath.h>
 #include <Utils/ImGuiHistogramQueue.h>
+#include <Utils/ImGuiMessageBox.h>
 
 namespace AZ
 {
@@ -67,6 +68,7 @@ namespace AtomSampleViewer
         AZStd::function<bool()> m_isSupportedFunc;
         SamplePipelineType m_pipelineType = SamplePipelineType::RHI;
         AZ::ComponentDescriptor* m_componentDescriptor;
+        AZStd::string m_contentWarning;
 
         bool operator==(const SampleEntry& other)
         {
@@ -200,6 +202,8 @@ namespace AtomSampleViewer
         static constexpr uint32_t FrameTimeLogSize = 30;
         ImGuiHistogramQueue m_imGuiFrameTimer;
 
+        ImGuiMessageBox m_contentWarningDialog;
+
         bool m_showImGuiMetrics = false;
         bool m_showSampleHelper = false;
         bool m_showResizeViewportDialog = false;
@@ -228,10 +232,6 @@ namespace AtomSampleViewer
         bool m_canSwitchSample = true;
         bool m_canCaptureRADTM = true;
 
-        // 10 number keys 0-9
-        static constexpr size_t s_alphanumericCount = 10;
-        bool m_alphanumericNumbersDown[s_alphanumericCount];
-
         bool m_exitRequested = false;
 
         AzFramework::EntityContextId m_entityContextId;

+ 5 - 0
Gem/Code/Source/SceneReloadSoakTestComponent.h

@@ -27,6 +27,11 @@ namespace AtomSampleViewer
         using Base = EntityLatticeTestComponent;
     public:
         AZ_COMPONENT(SceneReloadSoakTestComponent, "{5D0B03A6-F7B9-4952-90AB-C91306229964}", EntityLatticeTestComponent);
+
+        // Instead of using the CommonPhotosensitiveWarning, I used a custom message here that specifically calls out headaches and nausea
+        // as I've personally experienced those while looking at this sample, even though I don't otherwise consider myself to be photosensitive.
+        static constexpr const char ContentWarning[] = "This sample has lots of flashing, may cause headaches and nausea, or may cause seizures for people with certain photosensitivity.";
+
         SceneReloadSoakTestComponent() = default;
 
         static void Reflect(AZ::ReflectContext* context);

+ 2 - 2
Gem/Code/Source/ShaderReloadTestComponent.h

@@ -8,10 +8,10 @@
 
 #pragma once
 
+#include <AtomSampleComponent.h>
 #include <Atom/Bootstrap/DefaultWindowBus.h>
 #include <Atom/Feature/ImGui/ImGuiUtils.h>
 
-#include <AzCore/Component/Component.h>
 #include <AzCore/Component/EntityBus.h>
 #include <AzCore/Component/TickBus.h>
 
@@ -28,7 +28,7 @@ namespace AtomSampleViewer
     // to render a FullscreenTrianglePass, with the purpose on validating that the
     // shader reload notification events work properly.
     class ShaderReloadTestComponent final
-        : public AZ::Component
+        : public AtomSampleComponent
         , public AZ::Render::Bootstrap::DefaultWindowNotificationBus::Handler
         , public AZ::TickBus::Handler
     {

+ 2 - 0
Gem/Code/atomsampleviewergem_private_files.cmake

@@ -7,6 +7,8 @@
 #
 
 set(FILES
+    Source/AtomSampleComponent.cpp
+    Source/AtomSampleComponent.h
     Source/AtomSampleViewerOptions.h
     Source/AtomSampleViewerSystemComponent.cpp
     Source/AtomSampleViewerSystemComponent.h