Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions Community.UI.Animation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Facepunch.Extend;
using System.IO;

#if CLIENT

public partial class CommunityEntity
{
private class Animation : FacepunchBehaviour
{
public List<AnimationProperty> properties = new List<AnimationProperty>();

public List<UnityEngine.UI.Graphic> cachedGraphics = new List<UnityEngine.UI.Graphic>();

public bool isHidden = false;

public bool isKilled = false;

public void Start()
{
CacheGraphics();
foreach(var prop in properties)
{
prop.anim = this;
prop.routine = StartCoroutine(prop.Animate());
}
}

public void Kill()
{
isKilled = true;
foreach(var prop in properties)
{
StopCoroutine(prop.routine);
}
properties.Clear();
}
private void OnDestroy(){
if(!isKilled) Kill();
}

public void CacheGraphics(){
cachedGraphics.Clear();
gameObject.GetComponents<UnityEngine.UI.Graphic>(cachedGraphics);
}
public void ToggleTCulling(bool b){
foreach(var c in cachedGraphics){
c.cullTransparentMesh = b;
}
}
public void WaitToggleHidden(float delay = 0f){
if(delay <= 0f) ToggleTCulling(true);
else Invoke(new Action(() => {
ToggleTCulling(true);
isHidden = true;
}), delay);
}
}

private class AnimationProperty
{
public float duration = 0f;
public float delay = 0f;
public int repeat = 0;
public bool repeatDelay = 0f;
public string type;
public string from;
public string to;

public Animation anim;

public Coroutine routine;

public int completedRounds = 0;

public IEnumerator Animate()
{
if(delay > 0f) yield return new WaitForSeconds(delay);

if(repeatDelay <= 0f) repeatDelay = duration;

do
{
AnimateProperty();
completedRounds++;
if(repeatDelay > 0f) yield return new WaitForSeconds(repeatDelay);
else yield return null;
}
while(repeat < 0 || (repeat > 0 && completedRounds <= repeat));
}

public void AnimateProperty()
{
switch(type){
case "Opacity":
{
float fromOpacity;
float toOpacity;

// we need a valid toOpacity
if(!float.TryParse(to, out toOpacity)) break;
// unlike the toOpacity, a from value is optional. if we omit a from value the crossfade will instead use the current alpha
float.TryParse(from, out fromOpacity);
// disable TCulling if the toOpacity or FromOpacity are Higher than 0f, if the fromOpacity check was ommited this wouldnt trigger if its an animation from > 0 to 0
if(anim.isHidden && toOpacity > 0f || (fromOpacity != null && fromOpacity > 0f)){
anim.ToggleTCulling(false);
anim.isHidden = false;
}
foreach(var c in anim.cachedGraphics){
if(fromOpacity != null) c.canvasRenderer.SetAlpha(fromOpacity);
c.CrossFadeAlpha(toOpacity, duration, true);
}
if(!anim.isHidden && toOpacity <= 0f) anim.WaitToggleHidden(duration);

break;
}
case "Color":
{
Color fromColor = ColorEx.Parse(from);
Color toColor = ColorEx.Parse(to);

//dont use the from color if the from value was ommited
bool useFrom = string.IsNullOrEmpty(from);

foreach(var c in anim.cachedGraphics){
if(useFrom && !anim.isHidden) c.canvasRenderer.SetColor(fromColor);
c.CrossFadeColor(toColor, (anim.isHidden ? 0f : duration), true, false);
}

break;
}
case "ColorWithAlpha":
{
Color fromColor = ColorEx.Parse(from);
Color toColor = ColorEx.Parse(to);

//dont use the from color if the from value was ommited
bool useFrom = string.IsNullOrEmpty(from);
if(anim.isHidden && toColor.a > 0f || (useFrom && fromColor.a > 0f)){
anim.ToggleTCulling(false);
anim.isHidden = false;
}
bool doInstant = toColor.a <= 0f && (useFrom && fromColor.a <= 0f) || anim.isHidden;
foreach(var c in anim.cachedGraphics){
if(useFrom && !doInstant) c.canvasRenderer.SetColor(fromColor);
c.CrossFadeColor(toColor, (doInstant ? 0f : duration), true, true);
}

if(!anim.isHidden && toColor.a <= 0f) anim.WaitToggleHidden(duration);

break;
}
}
}
}
}

#endif
33 changes: 32 additions & 1 deletion CommunityEntity.UI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ public void AddUI( RPCMessage msg )
{
CreateComponents( go, component.Obj );
}

Animation anim = go.GetComponent<Animation>();
if(anim){
if(anim.properties.Count == 0) Object.Destroy(anim);
else anim.Start();
}

if ( json.ContainsKey( "fadeOut" ) )
{
Expand All @@ -104,7 +110,7 @@ private GameObject FindPanel( string name )

private void CreateComponents( GameObject go, JSON.Object obj )
{
//
//
// This is the 'stupid' but 'safe & predictable way of doing this.
//
switch ( obj.GetString( "type", "UnityEngine.UI.Text" ) )
Expand Down Expand Up @@ -321,6 +327,25 @@ private void CreateComponents( GameObject go, JSON.Object obj )
go.AddComponent<NeedsKeyboard>();
break;
}
case "Animation":
{
// Ensure there's only ever one Animation Component per gameObject, adding onto their existing Properties if one allready exists
Animation anim = go.GetComponent<Animation>();
if(!anim) anim = go.AddComponent<Animation>();
foreach(var prop in Obj.GetArray("properties"))
{
anim.properties.Add(new AnimationProperty{
duration = prop.GetFloat("duration", 0f),
delay = prop.GetFloat("delay", 0f),
repeat = prop.GetInt("repeat", 0),
repeatDelay = prop.GetFloat("repeatDelay", 0f),
type = prop.GetString("type", null),
from = prop.GetString("from", null),
to = prop.GetString("to", null)
});
}
break;
}
}
}

Expand Down Expand Up @@ -386,6 +411,12 @@ private void DestroyPanel( string pnlName )
if ( !panel )
return;


var animation = panel.GetComponent<Animation>();
if(animation){
animation.Kill();
}

var fadeOut = panel.GetComponent<FadeOut>();
if ( fadeOut )
{
Expand Down