@ -52,8 +52,13 @@ namespace Fungus
OffsetRight
}
[AddComponentMenu("")]
/// <summary>
/// Controls the Portrait sprites on stage
/// Controls the Portrait sprites on stage.
///
/// Is only really used via Stage, it's child class. This class continues to exist to support existing API
/// dependant code. All functionality is stage dependant.
/// </summary>
public class PortraitController : MonoBehaviour
{
@ -104,7 +109,7 @@ namespace Fungus
// if no previous portrait, use default portrait
if ( options . character . State . portrait = = null )
{
options . character . State . portrait = options . character . ProfileSprite ;
options . character . State . SetPortraitImageBySprite ( options . character . ProfileSprite ) ;
}
// Selected "use previous portrait"
@ -183,30 +188,56 @@ namespace Fungus
/// <param name="character"></param>
/// <param name="fadeDuration"></param>
protected virtual void CreatePortraitObject ( Character character , float fadeDuration )
{
if ( character . State . holder = = null )
{
character . State . holder = new GameObject ( character . name + " holder" ,
typeof ( RectTransform )
//typeof(CanvasRenderer),
//typeof(Image)
) . GetComponent < RectTransform > ( ) ;
// Set it to be a child of the stage
character . State . holder . transform . SetParent ( stage . PortraitCanvas . transform , false ) ;
SetRectTransform ( character . State . holder , stage . DefaultPosition . GetComponent < RectTransform > ( ) ) ;
}
if ( character . State . allPortraits . Count = = 0 )
{
foreach ( var item in character . Portraits )
{
// Create a new portrait object
GameObject portraitObj = new GameObject ( character . name ,
GameObject po = new GameObject ( item . name ,
typeof ( RectTransform ) ,
typeof ( CanvasRenderer ) ,
typeof ( Image ) ) ;
// Set it to be a child of the stage
portraitObj . transform . SetParent ( stage . PortraitCanvas . transform , true ) ;
po . transform . SetParent ( character . State . holder , fals e) ;
// Configure the portrait image
Image portraitImage = portraitObj . GetComponent < Image > ( ) ;
portraitImage . preserveAspect = true ;
portraitImage . overrideSprite = character . ProfileSprite ;
portraitImage . color = new Color ( 1f , 1f , 1f , 0f ) ;
Image pi = po . GetComponent < Image > ( ) ;
pi . preserveAspect = true ;
pi . s prite = item ;
pi . color = new Color ( 1f , 1f , 1f , 0f ) ;
// LeanTween doesn't handle 0 duration properly
float duration = ( fadeDuration > 0f ) ? fadeDuration : float . Epsilon ;
if ( item = = character . ProfileSprite )
{
character . State . portraitImage = pi ;
}
// Fade in character image (first time)
LeanTween . alpha ( portraitImage . transform as RectTransform , 1f , duration ) . setEase ( stage . FadeEaseType ) . setRecursive ( false ) ;
//expand to fit parent
RectTransform rt = po . GetComponent < RectTransform > ( ) ;
rt . sizeDelta = Vector2 . zero ;
rt . anchorMin = Vector2 . zero ;
rt . anchorMax = Vector2 . one ;
rt . pivot = Vector2 . one * 0.5f ;
rt . ForceUpdateRectTransforms ( ) ;
// Tell character about portrait image
character . State . portraitImage = portraitImage ;
character . State . allPortraits . Add ( pi ) ;
}
}
}
protected virtual IEnumerator WaitUntilFinished ( float duration , Action onComplete = null )
@ -232,39 +263,30 @@ namespace Fungus
protected virtual void SetupPortrait ( PortraitOptions options )
{
SetRectTransform ( options . character . State . portraitImage . rectTransform , options . fromPosition ) ;
if ( options . character . State . holder = = null )
return ;
SetRectTransform ( options . character . State . holder , options . fromPosition ) ;
if ( options . character . State . facing ! = options . character . PortraitsFace )
{
options . character . State . portraitImage . rectTransform . localScale = new Vector3 ( - 1f , 1f , 1f ) ;
options . character . State . holder . localScale = new Vector3 ( - 1f , 1f , 1f ) ;
}
else
{
options . character . State . portraitImage . rectTransform . localScale = new Vector3 ( 1f , 1f , 1f ) ;
options . character . State . holder . localScale = new Vector3 ( 1f , 1f , 1f ) ;
}
if ( options . facing ! = options . character . PortraitsFace )
{
options . character . State . portraitImage . rectTransform . localScale = new Vector3 ( - 1f , 1f , 1f ) ;
options . character . State . holder . localScale = new Vector3 ( - 1f , 1f , 1f ) ;
}
else
{
options . character . State . portraitImage . rectTransform . localScale = new Vector3 ( 1f , 1f , 1f ) ;
options . character . State . holder . localScale = new Vector3 ( 1f , 1f , 1f ) ;
}
}
protected virtual void DoMoveTween ( Character character , RectTransform fromPosition , RectTransform toPosition , float moveDuration , Boolean waitUntilFinished )
{
PortraitOptions options = new PortraitOptions ( true ) ;
options . character = character ;
options . fromPosition = fromPosition ;
options . toPosition = toPosition ;
options . moveDuration = moveDuration ;
options . waitUntilFinished = waitUntilFinished ;
DoMoveTween ( options ) ;
}
protected virtual void DoMoveTween ( PortraitOptions options )
{
CleanPortraitOptions ( options ) ;
@ -273,7 +295,8 @@ namespace Fungus
float duration = ( options . moveDuration > 0f ) ? options . moveDuration : float . Epsilon ;
// LeanTween.move uses the anchoredPosition, so all position images must have the same anchor position
LeanTween . move ( options . character . State . portraitImage . gameObject , options . toPosition . position , duration ) . setEase ( stage . FadeEaseType ) ;
LeanTween . move ( options . character . State . holder . gameObject , options . toPosition . position , duration )
. setEase ( stage . FadeEaseType ) ;
if ( options . waitUntilFinished )
{
@ -281,22 +304,20 @@ namespace Fungus
}
}
#region Public members
/// <summary>
/// Performs a deep copy of all values from one RectTransform to another.
/// </summary>
public static void SetRectTransform ( RectTransform oldRectTransform , RectTransform newRectTransfor m)
public static void SetRectTransform ( RectTransform target , RectTransform fro m)
{
oldRectTransform . eulerAngles = newRectTransfor m. eulerAngles ;
oldRectTransform . position = newRectTransfor m. position ;
oldRectTransform . rotation = newRectTransfor m. rotation ;
oldRectTransform . anchoredPosition = newRectTransfor m. anchoredPosition ;
oldRectTransform . sizeDelta = newRectTransfor m. sizeDelta ;
oldRectTransform . anchorMax = newRectTransfor m. anchorMax ;
oldRectTransform . anchorMin = newRectTransfor m. anchorMin ;
oldRectTransform . pivot = newRectTransfor m. pivot ;
oldRectTransform . localScale = newRectTransfor m. localScale ;
target . eulerAngles = fro m. eulerAngles ;
target . position = fro m. position ;
target . rotation = fro m. rotation ;
target . anchoredPosition = fro m. anchoredPosition ;
target . sizeDelta = fro m. sizeDelta ;
target . anchorMax = fro m. anchorMax ;
target . anchorMin = fro m. anchorMin ;
target . pivot = fro m. pivot ;
target . localScale = fro m. localScale ;
}
/// <summary>
@ -354,16 +375,6 @@ namespace Fungus
}
}
/// <summary>
/// Moves Character in front of other characters on stage
/// </summary>
public virtual void MoveToFront ( Character character )
{
PortraitOptions options = new PortraitOptions ( true ) ;
options . character = character ;
MoveToFront ( CleanPortraitOptions ( options ) ) ;
}
/// <summary>
/// Moves Character in front of other characters on stage
@ -375,51 +386,6 @@ namespace Fungus
FinishCommand ( options ) ;
}
/// <summary>
/// Shows character at a named position in the stage
/// </summary>
/// <param name="character"></param>
/// <param name="position">Named position on stage</param>
public virtual void Show ( Character character , string position )
{
PortraitOptions options = new PortraitOptions ( true ) ;
options . character = character ;
options . fromPosition = options . toPosition = stage . GetPosition ( position ) ;
Show ( options ) ;
}
/// <summary>
/// Shows character moving from a position to a position
/// </summary>
/// <param name="character"></param>
/// <param name="portrait"></param>
/// <param name="fromPosition">Where the character will appear</param>
/// <param name="toPosition">Where the character will move to</param>
public virtual void Show ( Character character , string portrait , string fromPosition , string toPosition )
{
PortraitOptions options = new PortraitOptions ( true ) ;
options . character = character ;
options . portrait = character . GetPortrait ( portrait ) ;
options . fromPosition = stage . GetPosition ( fromPosition ) ;
options . toPosition = stage . GetPosition ( toPosition ) ;
options . move = true ;
Show ( options ) ;
}
/// <summary>
/// From lua, you can pass an options table with named arguments
/// example:
/// stage.show{character=jill, portrait="happy", fromPosition="right", toPosition="left"}
/// Any option available in the PortraitOptions is available from Lua
/// </summary>
/// <param name="optionsTable">Moonsharp Table</param>
public virtual void Show ( Table optionsTable )
{
Show ( PortraitUtil . ConvertTableToPortraitOptions ( optionsTable , stage ) ) ;
}
/// <summary>
/// Show portrait with the supplied portrait options
/// </summary>
@ -454,39 +420,17 @@ namespace Fungus
// LeanTween doesn't handle 0 duration properly
float duration = ( options . fadeDuration > 0f ) ? options . fadeDuration : float . Epsilon ;
// Fade out a duplicate of the existing portrait image
if ( options . character . State . portraitImage ! = null & & options . character . State . portraitImage . overrideSprite ! = null )
{
GameObject tempGO = GameObject . Instantiate ( options . character . State . portraitImage . gameObject ) ;
var prevPortrait = options . character . State . portrait ;
//Fix for white box issue introduced by unity UI circa 2019.1
for ( int i = 0 ; i < tempGO . transform . childCount ; i + + )
if ( options . character . State . portrait ! = null & & options . character . State . portrait ! = options . portrait )
{
DestroyImmediate ( tempGO . transform . GetChild ( i ) . gameObject ) ;
LeanTween . alpha ( options . character . State . portraitImage . rectTransform , 0f , duration )
. setEase ( stage . FadeEaseType )
. setRecursive ( false ) ;
}
tempGO . transform . SetParent ( options . character . State . portraitImage . transform , false ) ;
tempGO . transform . localPosition = Vector3 . zero ;
tempGO . transform . localScale = options . character . State . position . localScale ;
Image tempImage = tempGO . GetComponent < Image > ( ) ;
tempImage . overrideSprite = options . character . State . portraitImage . overrideSprite ;
tempImage . preserveAspect = true ;
tempImage . color = options . character . State . portraitImage . color ;
LeanTween . alpha ( tempImage . rectTransform , 0f , duration ) . setEase ( stage . FadeEaseType ) . setOnComplete ( ( ) = > {
Destroy ( tempGO ) ;
} ) . setRecursive ( false ) ;
}
// Fade in the new sprite image
if ( options . character . State . portraitImage . overrideSprite ! = options . portrait | |
options . character . State . portraitImage . color . a < 1f )
{
options . character . State . portraitImage . overrideSprite = options . portrait ;
options . character . State . portraitImage . color = new Color ( 1f , 1f , 1f , 0f ) ;
options . character . State . SetPortraitImageBySprite ( options . portrait ) ;
LeanTween . alpha ( options . character . State . portraitImage . rectTransform , 1f , duration ) . setEase ( stage . FadeEaseType ) . setRecursive ( false ) ;
}
DoMoveTween ( options ) ;
@ -497,14 +441,117 @@ namespace Fungus
stage . CharactersOnStage . Add ( options . character ) ;
}
MoveToFront ( options ) ;
// Update character state after showing
options . character . State . onScreen = true ;
options . character . State . display = DisplayType . Show ;
options . character . State . portrait = options . portrait ;
options . character . State . facing = options . facing ;
options . character . State . position = options . toPosition ;
}
/// <summary>
/// Hide portrait with provided options
/// </summary>
public virtual void Hide ( PortraitOptions options )
{
CleanPortraitOptions ( options ) ;
if ( options . character . State . display = = DisplayType . None )
{
return ;
}
SetupPortrait ( options ) ;
// LeanTween doesn't handle 0 duration properly
float duration = ( options . fadeDuration > 0f ) ? options . fadeDuration : float . Epsilon ;
LeanTween . alpha ( options . character . State . portraitImage . rectTransform , 0f , duration ) . setEase ( stage . FadeEaseType ) . setRecursive ( false ) ;
DoMoveTween ( options ) ;
//update character state after hiding
options . character . State . onScreen = false ;
options . character . State . facing = options . facing ;
options . character . State . position = options . toPosition ;
options . character . State . display = DisplayType . Hide ;
if ( stage . CharactersOnStage . Remove ( options . character ) )
{
}
FinishCommand ( options ) ;
}
/// <summary>
/// Sets the dimmed state of a character on the stage.
/// </summary>
public virtual void SetDimmed ( Character character , bool dimmedState )
{
if ( character . State . dimmed = = dimmedState )
{
return ;
}
character . State . dimmed = dimmedState ;
Color targetColor = dimmedState ? stage . DimColor : Color . white ;
// LeanTween doesn't handle 0 duration properly
float duration = ( stage . FadeDuration > 0f ) ? stage . FadeDuration : float . Epsilon ;
LeanTween . color ( character . State . portraitImage . rectTransform , targetColor , duration ) . setEase ( stage . FadeEaseType ) . setRecursive ( false ) ;
}
#region Overloads and Helpers
/// <summary>
/// Shows character at a named position in the stage
/// </summary>
/// <param name="character"></param>
/// <param name="position">Named position on stage</param>
public virtual void Show ( Character character , string position )
{
PortraitOptions options = new PortraitOptions ( true ) ;
options . character = character ;
options . fromPosition = options . toPosition = stage . GetPosition ( position ) ;
Show ( options ) ;
}
/// <summary>
/// Shows character moving from a position to a position
/// </summary>
/// <param name="character"></param>
/// <param name="portrait"></param>
/// <param name="fromPosition">Where the character will appear</param>
/// <param name="toPosition">Where the character will move to</param>
public virtual void Show ( Character character , string portrait , string fromPosition , string toPosition )
{
PortraitOptions options = new PortraitOptions ( true ) ;
options . character = character ;
options . portrait = character . GetPortrait ( portrait ) ;
options . fromPosition = stage . GetPosition ( fromPosition ) ;
options . toPosition = stage . GetPosition ( toPosition ) ;
options . move = true ;
Show ( options ) ;
}
/// <summary>
/// From lua, you can pass an options table with named arguments
/// example:
/// stage.show{character=jill, portrait="happy", fromPosition="right", toPosition="left"}
/// Any option available in the PortraitOptions is available from Lua
/// </summary>
/// <param name="optionsTable">Moonsharp Table</param>
public virtual void Show ( Table optionsTable )
{
Show ( PortraitUtil . ConvertTableToPortraitOptions ( optionsTable , stage ) ) ;
}
/// <summary>
/// Simple show command that shows the character with an available named portrait
/// </summary>
@ -568,56 +615,27 @@ namespace Fungus
}
/// <summary>
/// Hide portrait with provided options
/// Moves Character in front of other characters on stage
/// </summary>
public virtual void Hide ( PortraitOptions options )
public virtual void MoveToFront ( Character character )
{
CleanPortraitOptions ( options ) ;
PortraitOptions options = new PortraitOptions ( true ) ;
options . character = character ;
if ( options . character . State . display = = DisplayType . None )
{
return ;
MoveToFront ( CleanPortraitOptions ( options ) ) ;
}
SetupPortrait ( options ) ;
// LeanTween doesn't handle 0 duration properly
float duration = ( options . fadeDuration > 0f ) ? options . fadeDuration : float . Epsilon ;
LeanTween . alpha ( options . character . State . portraitImage . rectTransform , 0f , duration ) . setEase ( stage . FadeEaseType ) . setRecursive ( false ) ;
DoMoveTween ( options ) ;
stage . CharactersOnStage . Remove ( options . character ) ;
//update character state after hiding
options . character . State . onScreen = false ;
options . character . State . portrait = options . portrait ;
options . character . State . facing = options . facing ;
options . character . State . position = options . toPosition ;
options . character . State . display = DisplayType . Hide ;
FinishCommand ( options ) ;
}
/// <summary>
/// Sets the dimmed state of a character on the stage.
/// </summary>
public virtual void SetDimmed ( Character character , bool dimmedState )
{
if ( character . State . dimmed = = dimmedState )
protected virtual void DoMoveTween ( Character character , RectTransform fromPosition , RectTransform toPosition , float moveDuration , Boolean waitUntilFinished )
{
return ;
}
character . State . dimmed = dimmedState ;
Color targetColor = dimmedState ? stage . DimColor : Color . white ;
// LeanTween doesn't handle 0 duration properly
float duration = ( stage . FadeDuration > 0f ) ? stage . FadeDuration : float . Epsilon ;
PortraitOptions options = new PortraitOptions ( true ) ;
options . character = character ;
options . fromPosition = fromPosition ;
options . toPosition = toPosition ;
options . moveDuration = moveDuration ;
options . waitUntilFinished = waitUntilFinished ;
LeanTween . color ( character . State . portraitImage . rectTransform , targetColor , duration ) . setEase ( stage . FadeEaseType ) . setRecursive ( false ) ;
DoMoveTween ( options ) ;
}
#endregion