> ## Documentation Index
> Fetch the complete documentation index at: https://docs-unity.molca.id/llms.txt
> Use this file to discover all available pages before exploring further.

# Popup Modal Confirmation Implementation

> Complete guide to implementing popup modals with confirmation using PopupStep and modal UI components.

**Core Components:**

* `Assets/_MolcaSDK/_VR/Scripts/Scenario/Steps/PopupStep.cs` — Step that displays popup modal and validates confirmation
* `Assets/_MolcaSDK/_VR/Scripts/UI/Modal/ModalManager.cs` — Manages modal lifecycle and interaction
* `Assets/_MolcaSDK/_VR/Scripts/UI/Modal/PopupModalUI.cs` — Popup modal UI component with buttons and content display

## When to use

Popup Modal Confirmation — use this guide when implementing this interaction pattern in a VR training scenario.

## Role

This guide covers implementing **popup modals with confirmation** in VR training scenarios:

* **PopupStep** — Step that displays modal and waits for confirmation
* **ModalManager** — Centralized modal lifecycle management
* **PopupModalUI** — Visual modal component with title, message, and action buttons
* **Confirmation Logic** — Custom handlers for confirm/cancel/dismiss actions

Combined, these create guided confirmation experiences where trainees acknowledge, confirm, or make choices in modals, with optional follow-up actions based on their response.

## Setup Steps

### 1. Create Modal Content (Text Assets)

1. Create a GameObject to hold modal content configuration
2. Add a **PopupContent** ScriptableObject or data structure with:
   * **Title**: Modal headline (e.g., "Confirm Action")
   * **Message**: Modal body text (e.g., "Are you sure you want to proceed?")
   * **Confirm Button Label**: Primary action text (e.g., "Yes", "Confirm")
   * **Cancel Button Label**: Secondary action text (e.g., "No", "Cancel")
   * **Icon/Image**: Optional visual asset for modal header

<Frame hint="ScriptableObject or component showing popup content fields: title, message, button labels, and icon." caption="Popup Modal Content Configuration">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ptmolcateknologinusantara/images/features/vr/implementation/popup-modal-content-config.png" alt="PopupContent configuration with title, message, and button labels" />
</Frame>

### 2. Add PopupStep for Modal Control

1. Create or select a GameObject to hold the **PopupStep** component
2. Add **PopupStep** component
3. Configure in Inspector:
   * **Trigger Mode**: Select how modal appears
     * **On Activated** — Modal shows immediately when step becomes active (automatic)
     * **Manual Trigger** — Step waits for manual trigger event before showing modal (requires external input)
   * **Popup Content Ref**: Assign the PopupContent reference (or inline title/message)
   * **Modal Manager Ref**: Assign the ModalManager (auto-find if available)
   * **Confirm Button Target**: (Optional) Assign action to trigger on confirm
   * **Cancel Button Target**: (Optional) Assign action to trigger on cancel
   * **Complete On Confirm**: Enable if step should complete when user confirms
   * **Dismiss On Cancel**: Enable if step should dismiss when user cancels
   * **Show Overlay**: Enable for background fade/blocking overlay

<Frame hint="PopupStep Inspector showing trigger mode selection, content reference, manager assignment, and button action configuration." caption="PopupStep Configuration">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ptmolcateknologinusantara/images/features/vr/implementation/popupstep-inspector.png" alt="PopupStep component with trigger mode and all fields configured" />
</Frame>

### 3. Setup Modal UI Canvas and Buttons

1. Create a Canvas (Screen Space - Overlay recommended for modals)
2. Add **PopupModalUI** component to the Canvas
3. Configure in Inspector:
   * **Title Text**: Assign TextMeshProUGUI for modal headline
   * **Message Text**: Assign TextMeshProUGUI for modal body
   * **Confirm Button**: Assign Button component for primary action
   * **Cancel Button**: Assign Button component for secondary action
   * **Modal Background**: Assign Image component for modal panel
   * **Overlay Fade**: (Optional) Assign Image component for background fade

<Frame hint="PopupModalUI Inspector showing text components, button assignments, and visual element references." caption="PopupModalUI Setup">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ptmolcateknologinusantara/images/features/vr/implementation/popupmodalui-inspector.png" alt="PopupModalUI component with UI elements assigned" />
</Frame>

### 4. Wire PopupStep and PopupModalUI Together

1. On the **PopupStep** component, assign the **PopupModalUI** reference
2. On the **PopupModalUI** component, assign the **PopupStep** reference (for event callbacks)
3. Configure button callbacks:
   * **Confirm Button.onClick** → PopupStep.OnConfirm()
   * **Cancel Button.onClick** → PopupStep.OnCancel()
4. (Optional) Add **Overlay** GameObject with Image component for background fade during modal display

<Frame hint="PopupModalUI and PopupStep wired together with button callbacks visible in Inspector." caption="PopupStep and PopupModalUI Integration">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ptmolcateknologinusantara/images/features/vr/implementation/popupstep-modalui-wiring.png" alt="PopupStep and PopupModalUI integration with button callbacks" />
</Frame>

## How It Works

### PopupStep

**File:** `Assets/_MolcaSDK/_VR/Scripts/Scenario/Steps/PopupStep.cs`

Displays a modal and validates player confirmation:

#### On Activated Mode (Automatic)

1. **On step start** (`OnStepActivated`): Automatically initializes and shows modal
   * Resolves PopupContent reference
   * Passes content to PopupModalUI
   * Shows modal with fade overlay
   * Registers button callbacks
2. **On confirm** (`OnConfirmPressed`): Player presses confirm button
   * Triggers optional confirm action
   * If **Complete On Confirm** enabled: completes step
3. **On cancel** (`OnCancelPressed`): Player presses cancel button
   * Triggers optional cancel action
   * If **Dismiss On Cancel** enabled: dismisses modal without completing step
4. **On step end** (`OnStepCompleted`): Hides modal and overlay

#### Manual Trigger Mode (Awaiting Signal)

1. **On step start** (`OnStepActivated`): Initializes but does NOT show modal yet
   * Prepares PopupContent reference
   * Waits for manual trigger signal
   * Modal remains hidden, Canvas inactive
2. **On manual trigger** (`OnManualTrigger`): External event triggers modal display
   * Shows modal with fade overlay
   * Registers button callbacks
   * Same confirmation/cancellation flow as On Activated mode
3. **On confirm/cancel** → Same as On Activated mode
4. **On step end** (`OnStepCompleted`): Hides modal and overlay

**Key fields:**

* `triggerMode` — Trigger activation method (OnActivated or ManualTrigger)
* `popupContentRef` — PopupContent with title, message, button labels
* `modalManagerRef` — ModalManager reference (auto-finds if null)
* `confirmButtonTarget` — Action to trigger on confirm
* `cancelButtonTarget` — Action to trigger on cancel
* `completeOnConfirm` — Auto-complete step on confirm
* `dismissOnCancel` — Dismiss without completing on cancel
* `showOverlay` — Display background fade overlay

### PopupModalUI

**File:** `Assets/_MolcaSDK/_VR/Scripts/UI/Modal/PopupModalUI.cs`

Displays and manages popup modal UI:

1. **Initialize** (`SetContent`): Receives PopupContent and updates UI
   * Sets title text
   * Sets message text
   * Updates button labels
   * Shows icon (if provided)
2. **Show** (`ShowModal`): Reveals modal and optional overlay
   * Fades in modal canvas
   * Animates modal entrance (slide, scale, fade)
3. **Button Interaction**: Players interact with confirm/cancel buttons
   * Buttons trigger PopupStep callbacks
   * Optional haptic feedback on button press
4. **Hide** (`HideModal`): Dismisses modal and overlay
   * Fades out modal canvas
   * Animates modal exit

**Key fields:**

* `titleText` — TextMeshProUGUI for modal title
* `messageText` — TextMeshProUGUI for modal message
* `confirmButton` — Button component for confirm action
* `cancelButton` — Button component for cancel action
* `modalBackground` — Image for modal panel
* `overlayFade` — (Optional) Image for background overlay
* `showDuration` — Duration of show animation (default: 0.3s)
* `hideDuration` — Duration of hide animation (default: 0.3s)

### ModalManager

**File:** `Assets/_MolcaSDK/_VR/Scripts/UI/Modal/ModalManager.cs`

Centralized modal lifecycle management:

1. **ShowModal** — Queues and displays modal
2. **HideModal** — Dismisses active modal
3. **IsModalVisible** — Checks if modal currently shown
4. **SetContent** — Updates modal content before showing
5. **RegisterCallback** — Subscribes to modal events (confirm, cancel, dismiss)

***

## Expected Results & Interaction Flow

### Idle State

Step is not active. No modal visible. Background appears normal. Canvas is hidden.

### Step Activated (Modal Appears)

When **PopupStep** becomes active:

* **Modal Canvas** becomes visible (fade in)
* **Background Overlay** appears (semi-transparent fade)
* **Modal Panel** displays with animation (slide, scale, or fade)
* **Title and Message** populated from PopupContent
* **Confirm/Cancel Buttons** are interactive and highlighted
* Visual feedback signals "Make a choice"

### User Approaching Modal

As trainee's hand approaches buttons:

* **Buttons** show hover states (color change, glow, scale)
* **Cursor/Ray** highlights interactive button
* **Haptic Feedback** pulses on button proximity
* Visual feedback indicates "Button is interactive"

### Confirming Choice

Trainee presses confirm button:

* **Button** shows press animation (scale down, color change)
* **Haptic Feedback** pulses on button press
* **Modal** may show confirmation animation or immediate hide
* **Step** progresses or completes based on configuration

### Canceling or Dismissing

Trainee presses cancel button or outside modal:

* **Button** shows press animation
* **Modal** fades out with dismiss animation
* **Background Overlay** fades
* **Step** returns to waiting or dismisses entirely

### Step Complete

Confirmation/dismissal conditions met:

* **Modal** fully hidden
* **Overlay** fully faded
* **Step** fires `OnStepEnd` event
* **Canvas** returns to inactive state
* Interaction flow complete

## Implementation (Inspector Only)

For popup confirmation, **no code required**. Configure entirely in Inspector:

1. **PopupContent** — Title, message, button labels
2. **PopupStep** — Content reference, action configuration
3. **PopupModalUI** — Canvas, text, buttons setup
4. **ModalManager** — Lifecycle management (auto-find)

All components work together automatically through the step lifecycle.

## Troubleshooting

| Issue                          | Solution                                                                                                                                                      |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Modal not visible**          | Verify PopupModalUI Canvas is active and visible in scene; check Canvas is on correct layer; ensure PopupStep is assigned PopupModalUI reference              |
| **Buttons not responding**     | Confirm Confirm/Cancel Button components assigned in PopupModalUI; verify button callbacks wired to PopupStep methods; test in Play mode with cursor visible  |
| **Text not showing**           | Verify Title/Message TextMeshProUGUI assigned in PopupModalUI; check PopupContent has non-empty title/message; ensure text color contrasts with background    |
| **Overlay not fading**         | Check **Show Overlay** enabled in PopupStep; verify Overlay Image assigned in PopupModalUI; confirm overlay Canvas is on correct sorting order (behind modal) |
| **Modal animation not smooth** | Adjust **Show Duration** and **Hide Duration** in PopupModalUI (try 0.2-0.5s); verify Canvas has CanvasGroup for fade animation; check for frame rate issues  |
| **Step never completes**       | Verify **Complete On Confirm** enabled in PopupStep; check confirm button is actually being pressed; test with Debug.Log in PopupStep.OnConfirm()             |
| **Overlay blocks interaction** | Reduce overlay opacity or disable **Show Overlay** if not needed; ensure overlay Canvas is set to non-blocking (CanvasGroup.blocksRaycasts = false)           |
| **Multiple modals stacking**   | Check only one PopupStep active per sequence; verify ModalManager.HideModal() called on previous modal before showing new one                                 |

## Visual Examples

### Scene Setup

<Frame hint="Scene view showing modal Canvas, buttons, overlay layer, and PopupStep/PopupModalUI components." caption="Complete Popup Modal Scene Setup">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ptmolcateknologinusantara/images/features/vr/implementation/popup-modal-scene-setup.png" alt="Scene with modal canvas, buttons, and overlay" />
</Frame>

### Modal State Animation

<Frame hint="Animated sequence showing idle → modal appears → buttons interactive → confirm pressed → modal disappears." caption="Popup Modal Interaction Sequence (Animation)">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ptmolcateknologinusantara/images/features/vr/implementation/popup-modal-interaction-sequence.gif" alt="Complete popup modal interaction with animations" />
</Frame>

### Button States

<Frame hint="Close-up showing button states: default, hover, pressed, disabled." caption="Modal Button States and Feedback">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ptmolcateknologinusantara/images/features/vr/implementation/popup-modal-button-states.png" alt="Modal buttons showing default, hover, and pressed states" />
</Frame>

## Related

* [PopupStep](/vr/steps/popup-step) — Modal display and confirmation logic
* [ModalManager](/vr/ui/modal-manager) — Modal lifecycle and queue management
* [VR UI Widgets](/shared/ui-widgets) — Base UI component library
* [VR step auxiliaries](/vr/steps/vr-step-auxiliaries) — Integration with scoring, haptics, and info display
* [Step lifecycle events](/core/sequence-controller) — OnStepBegin, OnStepEnd event system
* [VR player manager](/vr/vr-player-manager) — Disable locomotion during modal interaction
