//Log Dir http://docs.unity3d.com/Manual/LogFiles.html using UnityEngine; using System.Collections; using System.Collections.Generic; using System; using System.IO; using System.Text; using System.Runtime.InteropServices; using UnityEngine.UI; public abstract class GenericPlayerManager : MonoBehaviour { private const string DEFAULT_ANIMATION = "_default"; private const string NONE_ANIMATION = "_defaultWORD"; private const float FADE_LENGTH = 0.6F; private const float WORD_DEFAULT_SPEED = 1.1F; private const float WORD_MAX_SPEED = 2F; // Velocidade da primeira letra de uma palavra private const float LETTER_FIRST_SPEED = 2.6F; // Velocidade das outras letras private const float LETTER_DEFAULT_SPEED = 3.1F; // Velocidade máxima de uma letra que o slider pode configurar private const float LETTER_MAX_SPEED = 4.6F; // Taxa de velocidade da primeira letra de uma palavra equivalente a velocidade de uma palavra private const float LETTER_FIRST_UNIT_SPEED = (LETTER_MAX_SPEED - LETTER_FIRST_SPEED) / (WORD_MAX_SPEED - WORD_DEFAULT_SPEED); // Taxa de velocidade das outras letras equivalente a velocidade de uma palavra private const float LETTER_UNIT_SPEED = (LETTER_MAX_SPEED - LETTER_DEFAULT_SPEED) / (WORD_MAX_SPEED - WORD_DEFAULT_SPEED); // Velocidade de reprodução de números private const float NUMBER_DEFAULT_SPEED = 1.5F; // Velocidade máxima de um número que o slider pode configurar private const float NUMBER_MAX_SPEED = 2.9F; // Taxa de velocidade equivalente a uma unidade de velocidade de uma palavra private const float NUMBER_UNIT_SPEED = (NUMBER_MAX_SPEED - NUMBER_DEFAULT_SPEED) / (WORD_MAX_SPEED - WORD_DEFAULT_SPEED); private static float hSliderValue = WORD_DEFAULT_SPEED; private float letterSpeed = LETTER_DEFAULT_SPEED; private float numberSpeed = NUMBER_DEFAULT_SPEED; protected string glosa = ""; private static String[] stringPos = { DEFAULT_ANIMATION };//vetor que sera usado para quebrar a glosa private AnimationClip aniClip; private GameObject AVATAR; private Animation COMPONENT_ANIMATION; public Text SUBTITLES; // Guarda os nomes das palavras ja carregadas. private HashSet loadedAssetBundles = new HashSet(); // Guarda os nomes das palavras que nao tem assetbundle. private HashSet nonexistentAssetBundles = new HashSet(); // Lista de animações sendo reproduzidas. // Utilizada para apresentar a legenda. private volatile Queue> animQueue = new Queue>(); // Listas de AnimationState de animações sendo reproduzidas. // Utilizadas para alterar a velocidade da animação quando há evento no slider. private volatile List wordStateList = new List(); private volatile List letterStateList = new List(); private volatile List numberStateList = new List(); // "play" flag. Indica se está carregando a glosa. private volatile bool loading = false; public virtual void Start() { //Caching.CleanCache(); AVATAR = GameObject.FindGameObjectWithTag("avatar");//referencia para o avatar COMPONENT_ANIMATION = AVATAR.GetComponent();//referencia para o componente animador do avatar Application.ExternalCall("onLoadPlayer");//var onLoadPlayer = function(){} } protected virtual void setSubtitle(string text) { SUBTITLES.text = text; } // Define a velocidade das animacões com base no slider da GUI public void setSlider(float x) { hSliderValue = x; letterSpeed = getProporcionalSpeed(LETTER_DEFAULT_SPEED, LETTER_UNIT_SPEED); numberSpeed = getProporcionalSpeed(NUMBER_DEFAULT_SPEED, NUMBER_UNIT_SPEED); foreach (AnimationState state in wordStateList) if (state != null) state.speed = hSliderValue; foreach (AnimationState state in letterStateList) if (state != null) state.speed = letterSpeed; foreach (AnimationState state in numberStateList) if (state != null) state.speed = numberSpeed; } private float getProporcionalSpeed(float speed, float unit) { return speed + (hSliderValue - WORD_DEFAULT_SPEED) * unit; } public void stop_animations() { StopCoroutine("loadAndPlay"); loading = false; stopAnimations(); } public void stopAnimations() { try { StopCoroutine("handleStates"); } catch (NullReferenceException nre) { Debug.Log("StopCoroutine handlestates nullreff::"+nre.ToString()); } setSubtitle(""); try { animQueue.Clear(); wordStateList.Clear(); letterStateList.Clear(); numberStateList.Clear(); } catch (NullReferenceException nre) { Debug.Log("SetQueueList null reff::"+nre.ToString()); } COMPONENT_ANIMATION.Stop(); COMPONENT_ANIMATION.CrossFade(DEFAULT_ANIMATION, FADE_LENGTH, PlayMode.StopAll); } /* * Manda reproduzir animação e adiciona a file de animações a serem reproduzidas. * * Caso não haja SUBTITLE, name será utilizado como SUBTITLE. * Caso não haja fadeLength, será atribuido FADE_LENGTH. * Caso não haja velocidade, hSliderValue será atribuída. */ private AnimationState playAnimation(string name, string subtitle, float speed) { try { AnimationState state = COMPONENT_ANIMATION.CrossFadeQueued(name, FADE_LENGTH, QueueMode.CompleteOthers); state.speed = speed; animQueue.Enqueue(new KeyValuePair(subtitle, name)); //Debug.Log("Loaded: " + name + " (" + state.speed + ")"); return state; } catch (NullReferenceException nre) { Debug.Log("'" + name + "' não foi encontrado!\n" + nre.ToString()); } return null; } private AnimationState playAnimation(string name, string subtitle) { return playAnimation(name, subtitle, hSliderValue); } private AnimationState playAnimation(string name) { return playAnimation(name, name); } /* * Destaca caractere de uma string. */ private string highlight(string word, int index) { string subtitle; if (index > 0) subtitle = word.Substring(0, index) + "-"; else subtitle = ""; subtitle += word[index]; if (index < word.Length - 1) subtitle += "-" + word.Substring(index + 1, word.Length - index - 1); else subtitle += "" + word.Substring(index + 1, word.Length - index - 1); return subtitle; } /** * Returns the asset bundle named aniName. * * @return AssetBundle - se for encontrado. * null - se ocorrer num erro. */ protected abstract WWW loadAssetBundle(string aniName); public void play() { if (loading) stop_animations(); StartCoroutine("loadAndPlay"); } IEnumerator loadAndPlay() { loading = true; try{ stopAnimations(); } catch (NullReferenceException nre) { nre.ToString(); } string lastAnimationSubtitle = ""; bool spelled = false; // Default playAnimation(DEFAULT_ANIMATION, "", 2F); StartCoroutine("handleStates"); stringPos = glosa.Split(' '); foreach (string aniName in stringPos) { try { if (String.IsNullOrEmpty(aniName)) continue; } catch (Exception e) { Debug.Log(e + " :: NotNullNotEmpty"); } bool nonexistent = nonexistentAssetBundles.Contains(aniName); bool loaded = loadedAssetBundles.Contains(aniName); if ( ! nonexistent && ! loaded) { // Função loadAssetBundle é definida pela classe filha WWW www = loadAssetBundle(aniName); if (www != null) { yield return www; AssetBundle bundle = null; if (www.error == null) bundle = www.assetBundle; if (bundle != null && ! String.IsNullOrEmpty(bundle.mainAsset.name)) { aniClip = bundle.mainAsset as AnimationClip; bundle.Unload(false); if (aniClip) { COMPONENT_ANIMATION.AddClip(aniClip, aniName); loadedAssetBundles.Add(aniName); loaded = true; } else Debug.Log ("Sinal \"" + aniName + "\" não carregado corretamente."); } } } // Reproduz palavra if (loaded) { if (spelled) { // Default playAnimation(DEFAULT_ANIMATION, lastAnimationSubtitle); spelled = false; } wordStateList.Add(playAnimation(aniName)); lastAnimationSubtitle = aniName; } // Soletra palavra else { // Se a animação não foi carregada e nem está marcada como não existente, // adiciona ao set de animações não existentes if ( ! nonexistent) nonexistentAssetBundles.Add(aniName); // Se já houve o soletramento de alguma palavra, reproduz animação default if (spelled) playAnimation(DEFAULT_ANIMATION, lastAnimationSubtitle, 1.6F); else spelled = true; bool defaultPlayed = false; // A reprodução da primeira letra deve ser longa para não ser cortada no fade letterSpeed = getProporcionalSpeed(LETTER_FIRST_SPEED, LETTER_FIRST_UNIT_SPEED); for (int i = 0; i < aniName.Length; i++) { char value = aniName[i]; // Se for uma letra if (value >= 65 && value <= 90) { letterStateList.Add(playAnimation(value.ToString(), highlight(aniName, i), letterSpeed)); } // Se for um número else if (value >= 48 && value <= 57) { numberStateList.Add(playAnimation(value.ToString(), highlight(aniName, i), numberSpeed)); } // Se for uma vírgula else if (value == 44) { wordStateList.Add(playAnimation(value.ToString(), highlight(aniName, i))); } // Não há animação else { // Reproduz animação default apenas uma vez if ( ! defaultPlayed) { defaultPlayed = true; playAnimation(DEFAULT_ANIMATION, aniName); // A reprodução da próxima letra deve ser longa para não ser cortada no fade letterSpeed = getProporcionalSpeed(LETTER_FIRST_SPEED, LETTER_FIRST_UNIT_SPEED); } Debug.Log("Animação \"" + value + "\" inexistente."); continue; } defaultPlayed = false; letterSpeed = getProporcionalSpeed(LETTER_DEFAULT_SPEED, LETTER_UNIT_SPEED); } lastAnimationSubtitle = aniName; } } // Default playAnimation(DEFAULT_ANIMATION, lastAnimationSubtitle); loading = false; } /* * Sincroniza as legendas com as animações. */ IEnumerator handleStates() { // Enquanto estiver executando a rotina "loadAndPlay" // ou existir animações na fila de reprodução while (loading || animQueue.Count > 0) { if (animQueue.Count > 0) { KeyValuePair pair = animQueue.Peek(); setSubtitle(pair.Key); while (COMPONENT_ANIMATION.IsPlaying(pair.Value)) yield return null; animQueue.Dequeue(); } else yield return null; setSubtitle(""); } wordStateList.Clear(); letterStateList.Clear(); numberStateList.Clear(); } }