wip : scenes transitions

This commit is contained in:
2026-07-17 18:30:24 +02:00
parent 6dd3db9a07
commit 50f65e99a7
23 changed files with 915 additions and 1171 deletions
@@ -1,4 +1,5 @@
using UnityEngine;
using UnityEngine.Video;
namespace OctoCore.Navigation.Data
{
@@ -27,6 +28,21 @@ namespace OctoCore.Navigation.Data
[Tooltip("Enable fade transition")]
public bool UseFadeTransition = true;
/// <summary>
/// Video clip played on the eyelid overlay while transitioning into this scene.
/// Optional — leave empty for a plain blink with no video.
/// </summary>
[Tooltip("Video clip played during the transition into this scene (optional)")]
public VideoClip TransitionClip;
/// <summary>
/// Material applied to the eyelid overlay's RawImage while this scene's transition
/// clip is playing (e.g. a sketch/bleed shader). Falls back to the overlay's default
/// material if left empty.
/// </summary>
[Tooltip("Material applied to the video overlay for this scene's transition (optional)")]
public Material TransitionMaterial;
#if UNITY_EDITOR
void OnValidate()
{
@@ -35,4 +51,4 @@ namespace OctoCore.Navigation.Data
}
#endif
}
}
}
@@ -1,4 +1,5 @@
using UnityEngine;
using UnityEngine.Video;
namespace OctoCore.Navigation.Data
{
@@ -29,9 +30,29 @@ namespace OctoCore.Navigation.Data
/// <summary>
/// Enable fade transition during teleport.
/// Disabled by default: teleporters already have their own stencil/mask visual
/// effect, so the eyelid blink transition is redundant unless explicitly enabled
/// for a specific teleporter that needs it.
/// </summary>
[Tooltip("Enable fade transition")]
public bool UseFadeTransition = true;
[Tooltip("Enable eyelid blink transition (usually left off, teleporters already have their own stencil effect)")]
public bool UseFadeTransition = false;
/// <summary>
/// Video clip played on the eyelid overlay while this teleport is in progress.
/// Only used if UseFadeTransition is enabled. Optional — leave empty for a plain
/// blink with no video.
/// </summary>
[Tooltip("Video clip played during this teleport, if UseFadeTransition is enabled (optional)")]
public VideoClip TransitionClip;
/// <summary>
/// Material applied to the eyelid overlay's RawImage while this teleporter's
/// transition clip is playing (e.g. a sketch/bleed shader). Only used if
/// UseFadeTransition is enabled. Falls back to the overlay's default material
/// if left empty.
/// </summary>
[Tooltip("Material applied to the video overlay for this teleport, if UseFadeTransition is enabled (optional)")]
public Material TransitionMaterial;
#if UNITY_EDITOR
void OnValidate()
@@ -41,4 +62,4 @@ namespace OctoCore.Navigation.Data
}
#endif
}
}
}
@@ -0,0 +1,36 @@
using System;
using UnityEngine;
using UnityEngine.Video;
namespace OctoCore.Transitions
{
/// <summary>
/// Contract for a scene-transition visual effect (eyelid blink, plain fade, etc.).
/// Lives inside the OctoCore package and has zero dependency on any concrete
/// implementation or third-party tweening library. OctoNavigation only ever
/// talks to this interface, never to a concrete type.
/// </summary>
public interface IOctoSceneTransition
{
/// <summary>True while a transition sequence is currently animating.</summary>
bool IsBusy { get; }
/// <summary>
/// Assigns the visual content (clip/material) to use for the next CloseEyes() call.
/// Pass a null clip for a plain transition with no video overlay.
/// </summary>
void SetClip(VideoClip clip, Material material);
/// <summary>Closes the transition over the given duration and invokes the callback on completion.</summary>
void CloseEyes(float duration, Action onComplete);
/// <summary>Opens the transition over the given duration and invokes the callback on completion.</summary>
void OpenEyes(float duration, Action onComplete);
/// <summary>Stops and hides any video overlay currently playing.</summary>
void HideVideo();
/// <summary>Reveals the video overlay after the given delay, if a clip is assigned.</summary>
void ShowVideoAfterDelay(float delay);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 602c52bb0cc632440a621c93bbd9d5ad
@@ -3,6 +3,7 @@ using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using OctoCore.Navigation.Data;
using OctoCore.Transitions;
#if OCTO_ADDRESSABLES
using UnityEngine.AddressableAssets;
@@ -50,7 +51,6 @@ namespace OctoCore.Navigation
public Action<OctoTeleporterData, OctoTeleporterData> OnTeleportCompleted;
private Coroutine _loadingCoroutine;
private OctoSceneFade _fadeCanvas;
private bool _setPlayerRotation;
public void Init(OctoSettings settings)
@@ -66,8 +66,11 @@ namespace OctoCore.Navigation
}
}
// Create fade canvas
CreateFadeCanvas();
// The concrete transition effect (eyelid blink, plain fade, etc.) lives outside
// this package and registers itself with OctoTransitionProvider at runtime.
// Nothing to instantiate here.
if (OctoTransitionProvider.Current == null)
Debug.LogWarning("[OctoNavigation] No IOctoSceneTransition registered with OctoTransitionProvider. Scene transitions will have no visual effect.");
if (OctoEvents.Instance)
OctoEvents.Instance.SetScenesInitialized();
@@ -136,18 +139,63 @@ namespace OctoCore.Navigation
}
}
/// <summary>
/// Resolves the video clip to use for a transition: the scene/teleporter's own
/// clip if assigned, otherwise the global default from FadeSettings.
/// </summary>
private UnityEngine.Video.VideoClip ResolveClip(UnityEngine.Video.VideoClip specific, OctoSettings.ScenesSettings.FadeTransitionSettings fadeSettings)
{
return specific != null ? specific : fadeSettings.DefaultTransitionClip;
}
/// <summary>
/// Resolves the material to use for a transition: the scene/teleporter's own
/// material if assigned, otherwise the global default from FadeSettings.
/// </summary>
private Material ResolveMaterial(Material specific, OctoSettings.ScenesSettings.FadeTransitionSettings fadeSettings)
{
return specific != null ? specific : fadeSettings.DefaultTransitionMaterial;
}
/// <summary>
/// Waits for IOctoSceneTransition.CloseEyes() to complete. Bridges the callback-based
/// transition API with this class's coroutine-based flow.
/// </summary>
private IEnumerator CloseEyesRoutine(IOctoSceneTransition transition, float duration)
{
bool done = false;
transition.CloseEyes(duration, () => done = true);
while (!done)
yield return null;
}
/// <summary>
/// Waits for IOctoSceneTransition.OpenEyes() to complete. Bridges the callback-based
/// transition API with this class's coroutine-based flow.
/// </summary>
private IEnumerator OpenEyesRoutine(IOctoSceneTransition transition, float duration)
{
bool done = false;
transition.OpenEyes(duration, () => done = true);
while (!done)
yield return null;
}
private IEnumerator LoadSceneCoroutine(OctoSceneData sceneData)
{
OnSceneLoadStarted?.Invoke(sceneData);
// Get global fade settings
OctoSettings.ScenesSettings.FadeTransitionSettings fadeSettings = OctoCore.Instance.Settings.Scenes.FadeSettings;
IOctoSceneTransition transition = OctoTransitionProvider.Current;
// Fade out
if (sceneData.UseFadeTransition && _fadeCanvas)
if (sceneData.UseFadeTransition && transition != null)
{
_fadeCanvas.FadeOut(fadeSettings.FadeOutDuration, fadeSettings.FadeColor);
yield return new WaitForSeconds(fadeSettings.FadeOutDuration);
transition.SetClip(ResolveClip(sceneData.TransitionClip, fadeSettings), ResolveMaterial(sceneData.TransitionMaterial, fadeSettings));
yield return CloseEyesRoutine(transition, fadeSettings.FadeOutDuration);
transition.ShowVideoAfterDelay(0f);
yield return new WaitForSeconds(fadeSettings.HoldClosedDuration);
}
// Check if using Addressables
@@ -165,10 +213,10 @@ namespace OctoCore.Navigation
}
// Fade in
if (sceneData.UseFadeTransition && _fadeCanvas)
if (sceneData.UseFadeTransition && transition != null)
{
_fadeCanvas.FadeIn(fadeSettings.FadeInDuration);
yield return new WaitForSeconds(fadeSettings.FadeInDuration);
yield return OpenEyesRoutine(transition, fadeSettings.FadeInDuration);
transition.HideVideo();
}
OnSceneLoadCompleted?.Invoke(sceneData);
@@ -200,12 +248,15 @@ namespace OctoCore.Navigation
{
// Get global fade settings
OctoSettings.ScenesSettings.FadeTransitionSettings fadeSettings = OctoCore.Instance.Settings.Scenes.FadeSettings;
IOctoSceneTransition transition = OctoTransitionProvider.Current;
// Fade out
if (teleporter.UseFadeTransition && _fadeCanvas)
if (teleporter.UseFadeTransition && transition != null)
{
_fadeCanvas.FadeOut(fadeSettings.FadeOutDuration, fadeSettings.FadeColor);
yield return new WaitForSeconds(fadeSettings.FadeOutDuration);
transition.SetClip(ResolveClip(teleporter.TransitionClip, fadeSettings), ResolveMaterial(teleporter.TransitionMaterial, fadeSettings));
yield return CloseEyesRoutine(transition, fadeSettings.FadeOutDuration);
transition.ShowVideoAfterDelay(0f);
yield return new WaitForSeconds(fadeSettings.HoldClosedDuration);
}
// Find target teleporter
@@ -222,10 +273,10 @@ namespace OctoCore.Navigation
}
// Fade in
if (teleporter.UseFadeTransition && _fadeCanvas)
if (teleporter.UseFadeTransition && transition != null)
{
_fadeCanvas.FadeIn(fadeSettings.FadeInDuration);
yield return new WaitForSeconds(fadeSettings.FadeInDuration);
yield return OpenEyesRoutine(transition, fadeSettings.FadeInDuration);
transition.HideVideo();
}
OnTeleportCompleted?.Invoke(null, teleporter);
@@ -235,12 +286,15 @@ namespace OctoCore.Navigation
{
// Get global fade settings
OctoSettings.ScenesSettings.FadeTransitionSettings fadeSettings = OctoCore.Instance.Settings.Scenes.FadeSettings;
IOctoSceneTransition transition = OctoTransitionProvider.Current;
// Fade out
if (teleporter.UseFadeTransition && _fadeCanvas)
if (teleporter.UseFadeTransition && transition != null)
{
_fadeCanvas.FadeOut(fadeSettings.FadeOutDuration, fadeSettings.FadeColor);
yield return new WaitForSeconds(fadeSettings.FadeOutDuration);
transition.SetClip(ResolveClip(teleporter.TransitionClip, fadeSettings), ResolveMaterial(teleporter.TransitionMaterial, fadeSettings));
yield return CloseEyesRoutine(transition, fadeSettings.FadeOutDuration);
transition.ShowVideoAfterDelay(0f);
yield return new WaitForSeconds(fadeSettings.HoldClosedDuration);
}
// Store pending teleporter
@@ -296,12 +350,13 @@ namespace OctoCore.Navigation
// Get global fade settings
OctoSettings.ScenesSettings.FadeTransitionSettings fadeSettings = OctoCore.Instance.Settings.Scenes.FadeSettings;
IOctoSceneTransition transition = OctoTransitionProvider.Current;
// Fade in
if (_fadeCanvas)
if (transition != null)
{
_fadeCanvas.FadeIn(fadeSettings.FadeInDuration);
yield return new WaitForSeconds(fadeSettings.FadeInDuration);
yield return OpenEyesRoutine(transition, fadeSettings.FadeInDuration);
transition.HideVideo();
}
OnTeleportCompleted?.Invoke(null, teleporter.TeleporterData);
@@ -321,13 +376,5 @@ namespace OctoCore.Navigation
OctoTeleporterProxy.Instance.Teleport(teleporter.transform.position);
}
}
private void CreateFadeCanvas()
{
GameObject fadeObj = new GameObject("OctoSceneFade");
GameObject.DontDestroyOnLoad(fadeObj);
_fadeCanvas = fadeObj.AddComponent<OctoSceneFade>();
_fadeCanvas.Initialize();
}
}
}
@@ -0,0 +1,18 @@
namespace OctoCore.Transitions
{
/// <summary>
/// Holds the currently active IOctoSceneTransition implementation.
/// The concrete implementation (e.g. an eyelid-blink component living outside the
/// OctoCore package, using LeanTween or any other tweening library) registers itself
/// here at runtime. OctoNavigation reads Current instead of referencing any concrete
/// type directly, keeping the package free of external dependencies.
/// </summary>
public static class OctoTransitionProvider
{
/// <summary>
/// The active transition implementation, or null if none has registered yet.
/// Callers in OctoCore must null-check before use.
/// </summary>
public static IOctoSceneTransition Current { get; set; }
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d238165ccb7dd4745895e54eb945e2d8
@@ -225,12 +225,14 @@ namespace OctoCore
{
/// <summary>
/// Fade in duration in seconds.
/// Also used as the eyelid opening duration for blink transitions.
/// </summary>
[Tooltip("Fade in duration")]
public float FadeInDuration = 0.5f;
/// <summary>
/// Fade out duration in seconds.
/// Also used as the eyelid closing duration for blink transitions.
/// </summary>
[Tooltip("Fade out duration")]
public float FadeOutDuration = 0.5f;
@@ -240,6 +242,27 @@ namespace OctoCore
/// </summary>
[Tooltip("Fade color")]
public Color FadeColor = Color.black;
/// <summary>
/// Time to hold the eyelids fully closed before reopening, on top of
/// whatever time the scene load or teleport itself takes.
/// </summary>
[Tooltip("Time to hold the eyelids fully closed before reopening")]
public float HoldClosedDuration = 0.1f;
/// <summary>
/// Fallback video clip used when a scene or teleporter doesn't specify
/// its own TransitionClip. Leave empty for a plain blink by default.
/// </summary>
[Tooltip("Fallback video clip used when a scene/teleporter has none assigned")]
public UnityEngine.Video.VideoClip DefaultTransitionClip;
/// <summary>
/// Fallback material applied to the video overlay when a scene or
/// teleporter doesn't specify its own TransitionMaterial.
/// </summary>
[Tooltip("Fallback material used when a scene/teleporter has none assigned")]
public Material DefaultTransitionMaterial;
}
/// <summary>