Commit d1e9f58446a8d973caacee939bd88f93172f9ffa

Authored by Mateus Lustosa
1 parent 376de3bb
Exists in master

Acentuacao e ç

Assets/Scenes/UI_disabled.unity
... ... @@ -807,6 +807,10 @@ Prefab:
807 807 propertyPath: avatarCollider
808 808 value:
809 809 objectReference: {fileID: 1772849664}
  810 + - target: {fileID: 11427452, guid: cd81d95d2fa8dc448b18a415b9009d43, type: 2}
  811 + propertyPath: fadeLength
  812 + value: 0.5
  813 + objectReference: {fileID: 0}
810 814 m_RemovedComponents: []
811 815 m_ParentPrefab: {fileID: 100100000, guid: cd81d95d2fa8dc448b18a415b9009d43, type: 2}
812 816 m_IsPrefabParent: 0
... ...
Assets/Scripts/GenericPlayerManager.txt
... ... @@ -1,605 +0,0 @@
1   -//Log Dir http://docs.unity3d.com/Manual/LogFiles.html
2   -using UnityEngine;
3   -using System.Collections;
4   -using System.Collections.Generic;
5   -using System;
6   -using System.IO;
7   -using System.Text;
8   -using System.Runtime.InteropServices;
9   -using UnityEngine.UI;
10   -
11   -public abstract class GenericPlayerManager : MonoBehaviour {
12   -
13   - private class AnimationReference
14   - {
15   - public string name;
16   - public string subtitle;
17   - public AnimationState state;
18   - public short type;
19   - public bool playing;
20   -
21   - public AnimationReference(string name, string subtitle, AnimationState state, short type)
22   - {
23   - this.name = name;
24   - this.subtitle = subtitle;
25   - this.state = state;
26   - this.type = type;
27   - this.playing = false;
28   - }
29   - }
30   -
31   - protected class DefaultSignSpeed
32   - {
33   - public static float DEFAULT = 1.1F;
34   - public static float DEFAULT_MAX = 2F;
35   -
36   - private float speed;
37   - private float max;
38   - // Relação entre a velocidade do tipo representado e a velocidade DEFAULT.
39   - private float unit;
40   -
41   - public DefaultSignSpeed()
42   - {
43   - this.speed = DEFAULT;
44   - this.max = DEFAULT_MAX;
45   - this.unit = 1F;
46   - }
47   -
48   - public DefaultSignSpeed(float defaultSpeed, float defaultMaxSpeed)
49   - {
50   - this.speed = defaultSpeed;
51   - this.max = defaultMaxSpeed;
52   - this.unit = (this.max - this.speed) / (DEFAULT_MAX - DEFAULT);
53   - }
54   -
55   - public float Speed {
56   - get { return this.speed; }
57   - set {
58   - this.speed = value;
59   - this.unit = calculateUnit();
60   - }
61   - }
62   - public float Max {
63   - get { return this.max; }
64   - set {
65   - this.speed = value;
66   - this.unit = calculateUnit();
67   - }
68   - }
69   - public float Unit {
70   - get { return this.unit; }
71   - }
72   -
73   - private float calculateUnit()
74   - {
75   - return (this.max - this.speed) / (DEFAULT_MAX - DEFAULT);
76   - }
77   -
78   - /*
79   - * Retorna velocidade em relação ao estado do slider.
80   - * @param slider - estado do slider (valor entre DefaultSignSpeed.DEFAULT e DefaultSignSpeed.DEFAULT_MAX)
81   - */
82   - public float getProporcionalSpeed(float slider)
83   - {
84   - return this.speed + (slider - DEFAULT) * this.unit;
85   - }
86   - }
87   -
88   - private const string DEFAULT_ANIMATION = "_default";
89   - private const string NONE_ANIMATION = "_defaultWORD";
90   -
91   - protected float fadeLength = 0.6F;
92   -
93   - protected DefaultSignSpeed defaultWordSpeed = new DefaultSignSpeed();
94   - protected DefaultSignSpeed defaultFirstLetterSpeed = new DefaultSignSpeed(2.1F, 2.8F);
95   - protected DefaultSignSpeed defaultLetterSpeed = new DefaultSignSpeed(3F, 4.3F);
96   - protected DefaultSignSpeed defaultNumberSpeed = new DefaultSignSpeed(1.5F, 2.9F);
97   -
98   - private const short TYPE_NONE = -1;
99   - private const short TYPE_WORD = 0;
100   - private const short TYPE_LETTER = 1;
101   - private const short TYPE_NUMBER = 2;
102   -
103   - private float hSlidersecond = DefaultSignSpeed.DEFAULT;
104   - private float wordSpeed = DefaultSignSpeed.DEFAULT;
105   - private float letterSpeed = DefaultSignSpeed.DEFAULT;
106   - private float numberSpeed = DefaultSignSpeed.DEFAULT;
107   -
108   - protected string glosa = "";
109   - private static String[] stringPos = { DEFAULT_ANIMATION };//vetor que sera usado para quebrar a glosa
110   -
111   - private GameObject AVATAR;
112   - private Animation COMPONENT_ANIMATION;
113   - private BoxCollider AVATAR_COLLIDER;
114   - public Text SUBTITLES;
115   -
116   - // Guarda os nomes das palavras ja carregadas.
117   - private HashSet<string> loadedAssetBundles = new HashSet<string>();
118   - // Guarda os nomes das palavras que nao tem assetbundle.
119   - private HashSet<string> nonexistentAssetBundles = new HashSet<string>();
120   -
121   - // Lista de animações sendo reproduzidas.
122   - // Utilizada para alterar velocidade e apresentar a legenda.
123   - private volatile Queue<AnimationReference> animQueue = new Queue<AnimationReference>();
124   -
125   - private volatile bool loadingSingleAnimation = false;
126   - private volatile bool loading = false;
127   - private volatile bool playing = false;
128   - private volatile bool paused = false;
129   -
130   - public virtual void Start()
131   - {
132   - this.wordSpeed = this.defaultWordSpeed.Speed;
133   - this.letterSpeed = this.defaultLetterSpeed.Speed;
134   - this.numberSpeed = this.defaultNumberSpeed.Speed;
135   -
136   - this.AVATAR = GameObject.FindGameObjectWithTag("avatar");//referencia para o avatar
137   - this.COMPONENT_ANIMATION = AVATAR.GetComponent<Animation>();//referencia para o componente animador do avatar
138   - this.AVATAR_COLLIDER = GameObject.FindGameObjectWithTag("avatar").GetComponent<BoxCollider>();
139   - }
140   -
141   - public bool isLoadingSingleAnimation() { return loadingSingleAnimation; }
142   - public bool isLoading() { return loading; }
143   - public bool isPlaying() { return playing; }
144   - public bool isPaused() { return paused; }
145   -
146   - /* Ativar ou desativar o colisor do avatar */
147   - public void SetAvatarCollider(bool isActive) {
148   - this.AVATAR_COLLIDER.enabled = isActive;
149   - }
150   -
151   - /* Mudar legenda */
152   - protected virtual void setSubtitle(string text) {
153   - this.SUBTITLES.text = text;
154   - }
155   -
156   - /* Define a velocidade das animacões com base no slider da GUI */
157   - public void setSlider(float x)
158   - {
159   - this.hSlidersecond = x;
160   -
161   - this.wordSpeed = this.defaultWordSpeed.getProporcionalSpeed(x);
162   - this.letterSpeed = this.defaultLetterSpeed.getProporcionalSpeed(x);
163   - this.numberSpeed = this.defaultNumberSpeed.getProporcionalSpeed(x);
164   -
165   - if ( ! paused)
166   - foreach (AnimationReference reference in this.animQueue)
167   - if (reference.type != TYPE_NONE && reference.state != null)
168   - reference.state.speed = getSpeedByType(reference.type);
169   - }
170   -
171   - private float getSpeedByType(short type)
172   - {
173   - switch (type)
174   - {
175   - case TYPE_WORD: return this.wordSpeed;
176   - case TYPE_LETTER: return this.letterSpeed;
177   - case TYPE_NUMBER: return this.numberSpeed;
178   - }
179   -
180   - return 2F;
181   - }
182   -
183   -
184   - public void stopAll()
185   - {
186   - StopCoroutine("loadAndPlay");
187   -
188   - this.loading = false;
189   -
190   - stopAnimations();
191   - }
192   -
193   - void stopAnimations()
194   - {
195   - try {
196   - StopCoroutine("handleStates");
197   - } catch (NullReferenceException nre) { Debug.Log("StopCoroutine handlestates nullreff::"+nre.ToString()); }
198   -
199   - setSubtitle("");
200   -
201   - try {
202   - animQueue.Clear();
203   - } catch (NullReferenceException nre) { Debug.Log("SetQueueList null reff::"+nre.ToString()); }
204   -
205   - COMPONENT_ANIMATION.Stop();
206   - COMPONENT_ANIMATION.CrossFade(DEFAULT_ANIMATION, fadeLength, PlayMode.StopAll);
207   -
208   - this.playing = false;
209   - this.paused = false;
210   - onPlayingStateChange();
211   - }
212   -
213   - /*
214   - * Manda reproduzir animação e adiciona a file de animações a serem reproduzidas.
215   - *
216   - * Caso não haja SUBTITLE, name será utilizado como SUBTITLE.
217   - * Caso não haja fadeLength, será atribuido fadeLength.
218   - * Caso não haja velocidade, hSlidersecond será atribuída.
219   - */
220   - private AnimationState playAnimation(short type, string name, string subtitle, float speed)
221   - {
222   - try
223   - {
224   - AnimationState state = COMPONENT_ANIMATION.CrossFadeQueued(name, fadeLength, QueueMode.CompleteOthers);
225   - state.speed = speed;
226   - animQueue.Enqueue(new AnimationReference(name, subtitle, state, type));
227   -
228   - return state;
229   - }
230   - catch (NullReferenceException nre)
231   - {
232   - Debug.Log("'" + name + "' não foi encontrado!\n" + nre.ToString());
233   - }
234   -
235   - return null;
236   - }
237   - private AnimationState playAnimation(short type, string name, string subtitle) {
238   - return playAnimation(type, name, subtitle, getSpeedByType(type));
239   - }
240   - private AnimationState playAnimation(short type, string name) {
241   - return playAnimation(type, name, name);
242   - }
243   -
244   -
245   - /**
246   - * Returns the asset bundle named aniName.
247   - *
248   - * @return AssetBundle - se for encontrado.
249   - * null - se ocorrer num erro.
250   - */
251   - protected abstract WWW loadAssetBundle(string aniName);
252   -
253   -
254   - /**
255   - * Listen to changes in the playing status.
256   - */
257   - protected abstract void onPlayingStateChange();
258   -
259   -
260   - public void switchPauseState(bool paused)
261   - {
262   - Debug.Log("switch to: " + (paused ? "paused" : "playing"));
263   -
264   - if (this.paused != paused)
265   - {
266   - this.paused = paused;
267   -
268   - foreach (AnimationReference reference in animQueue)
269   - if (reference.state != null)
270   - reference.state.speed = paused ? 0F : getSpeedByType(reference.type);
271   -
272   - onPlayingStateChange();
273   - }
274   - }
275   - public void switchPauseState()
276   - {
277   - switchPauseState( ! this.paused);
278   - }
279   -
280   - public bool play()
281   - {
282   - if (playing)
283   - switchPauseState();
284   - else
285   - play(true, true, true);
286   -
287   - return true;
288   - }
289   -
290   - public bool play(bool stopLoading, bool stopPlaying, bool forceLoading)
291   - {
292   - if (loading)
293   - {
294   - if (stopLoading)
295   - stopAll();
296   - else
297   - return false;
298   - }
299   - else if (playing)
300   - {
301   - if (stopPlaying)
302   - stopAnimations();
303   -
304   - else if ( ! forceLoading)
305   - return false;
306   - }
307   -
308   - StartCoroutine("loadAndPlay");
309   - return true;
310   - }
311   -
312   -
313   - /*
314   - * Destaca caractere de uma string.
315   - */
316   - private string highlight(string word, int index)
317   - {
318   - string subtitle = "";
319   - int last = 0;
320   -
321   - if (index == 0)
322   - //subtitle += "<b><color=white>" + word[0] + "</color></b>";
323   - subtitle += "<b>" + word[0] + "</b>";
324   - else
325   - subtitle += word[0];
326   -
327   - for (int i = 1; i < word.Length; i++)
328   - {
329   - if ((word[i] >= 65 && word[i] <= 90) || (word[i] >= 48 && word[i] <= 57))
330   - subtitle += "-";
331   -
332   - if (i == index || (last == index && word[i] == word[last]))
333   - {
334   - //subtitle += "<b><color=white>" + word[i] + "</color></b>";
335   - subtitle += "<b>" + word[i] + "</b>";
336   - if (i == index) last = i;
337   - }
338   - else
339   - {
340   - subtitle += word[i];
341   - last = i;
342   - }
343   - }
344   -
345   - return subtitle;
346   - }
347   -
348   - /**
349   - * Spells word.
350   - *
351   - * @return last animation's subtitle.
352   - */
353   - private string spellWord(string word)
354   - {
355   - string lastAnimationSubtitle = "";
356   - bool defaultPlayed = false;
357   -
358   - // A reprodução da primeira letra deve ser longa para não ser cortada no fade
359   - letterSpeed = defaultLetterSpeed.getProporcionalSpeed(hSlidersecond);
360   -
361   - for (int i = 0; i < word.Length; i++)
362   - {
363   - char second = word[i];
364   - lastAnimationSubtitle = highlight(word, i);
365   -
366   - // Se for uma letra
367   - if (second >= 65 && second <= 90)
368   - playAnimation(TYPE_LETTER, second.ToString(), lastAnimationSubtitle, letterSpeed);
369   -
370   - // Se for um número
371   - else if (second >= 48 && second <= 57)
372   - playAnimation(TYPE_NUMBER, second.ToString(), lastAnimationSubtitle, numberSpeed);
373   -
374   - // Se for uma vírgula
375   - else if (second == 44)
376   - playAnimation(TYPE_WORD, second.ToString(), lastAnimationSubtitle);
377   -
378   - // Não há animação
379   - else
380   - {
381   - // Reproduz animação default apenas uma vez
382   - if ( ! defaultPlayed)
383   - {
384   - defaultPlayed = true;
385   - playAnimation(TYPE_NONE, DEFAULT_ANIMATION, lastAnimationSubtitle);
386   -
387   - // A reprodução da próxima letra deve ser longa para não ser cortada no fade
388   - letterSpeed = defaultLetterSpeed.getProporcionalSpeed(hSlidersecond);
389   - }
390   -
391   - Debug.Log("Animação \"" + second + "\" inexistente.");
392   - continue;
393   - }
394   -
395   - defaultPlayed = false;
396   - letterSpeed = defaultLetterSpeed.getProporcionalSpeed(hSlidersecond);
397   - }
398   -
399   - return lastAnimationSubtitle;
400   - }
401   -
402   -
403   - protected IEnumerator loadAnimation(string name)
404   - {
405   - loadingSingleAnimation = true;
406   -
407   - // Função loadAssetBundle é definida pela classe filha
408   - WWW www = loadAssetBundle(name);
409   -
410   - if (www != null)
411   - {
412   - yield return www;
413   -
414   - AssetBundle bundle = null;
415   -
416   - if (www.error == null)
417   - bundle = www.assetBundle;
418   -
419   - if (bundle != null && ! String.IsNullOrEmpty(bundle.mainAsset.name))
420   - {
421   - AnimationClip aniClip = bundle.mainAsset as AnimationClip;
422   - bundle.Unload(false);
423   -
424   - if (aniClip)
425   - {
426   - COMPONENT_ANIMATION.AddClip(aniClip, name);
427   -
428   - // Reproduz palavra
429   - loadedAssetBundles.Add(name);
430   - yield break;
431   - }
432   - else Debug.Log ("Sinal \"" + name + "\" não carregado corretamente.");
433   - }
434   - }
435   -
436   - // Soletra palavra
437   - nonexistentAssetBundles.Add(name);
438   -
439   - loadingSingleAnimation = false;
440   - }
441   -
442   -
443   - private IEnumerator loadAndPlay()
444   - {
445   - loading = true;
446   - onPlayingStateChange();
447   -
448   - string lastAnimationSubtitle = "";
449   - bool spelled = false;
450   -
451   - // Default
452   - playAnimation(TYPE_NONE, DEFAULT_ANIMATION, "", 2F);
453   -
454   - if ( ! playing)
455   - {
456   - playing = true;
457   - StartCoroutine("handleStates");
458   - }
459   -
460   - stringPos = glosa.Split(' ');
461   -
462   - foreach (string aniName in stringPos)
463   - {
464   - try {
465   - if (String.IsNullOrEmpty(aniName)) continue;
466   - } catch (Exception e) {
467   - Debug.Log(e + " :: NotNullNotEmpty");
468   - }
469   -
470   - bool nonexistent = nonexistentAssetBundles.Contains(aniName);
471   - bool loaded = loadedAssetBundles.Contains(aniName);
472   -
473   - if ( ! nonexistent && ! loaded)
474   - {
475   - // Função loadAssetBundle é definida pela classe filha
476   - WWW www = loadAssetBundle(aniName);
477   -
478   - if (www != null)
479   - {
480   - yield return www;
481   -
482   - AssetBundle bundle = null;
483   -
484   - if (www.error == null)
485   - bundle = www.assetBundle;
486   -
487   - if (bundle != null && ! String.IsNullOrEmpty(bundle.mainAsset.name))
488   - {
489   - AnimationClip aniClip = bundle.mainAsset as AnimationClip;
490   - bundle.Unload(false);
491   -
492   - if (aniClip)
493   - {
494   - COMPONENT_ANIMATION.AddClip(aniClip, aniName);
495   -
496   - loadedAssetBundles.Add(aniName);
497   - loaded = true;
498   - }
499   - else Debug.Log ("Sinal \"" + aniName + "\" não carregado corretamente.");
500   - }
501   - }
502   - }
503   -
504   - // Reproduz palavra
505   - if (loaded)
506   - {
507   - if (spelled)
508   - {
509   - // Default
510   - playAnimation(TYPE_NONE, DEFAULT_ANIMATION, lastAnimationSubtitle);
511   - spelled = false;
512   - }
513   -
514   - bool isPunctuation = false;
515   -
516   - if (aniName[0] == '[')
517   - {
518   - if (aniName.Equals("[PONTO]") || aniName.Equals("[INTERROGACAO]") || aniName.Equals("[EXCLAMACAO]"))
519   - {
520   - isPunctuation = true;
521   - lastAnimationSubtitle = "";
522   - }
523   - else
524   - {
525   - lastAnimationSubtitle = aniName;
526   - }
527   - }
528   -
529   - if (isPunctuation)
530   - playAnimation(TYPE_WORD, aniName, lastAnimationSubtitle);
531   - else
532   - playAnimation(TYPE_WORD, aniName);
533   - }
534   - // Soletra palavra
535   - else
536   - {
537   - // Se a animação não foi carregada e nem está marcada como não existente,
538   - // adiciona ao set de animações não existentes
539   - if ( ! nonexistent)
540   - nonexistentAssetBundles.Add(aniName);
541   -
542   - Debug.Log("~~ To spell: " + aniName);
543   -
544   - if (aniName.Equals("[PONTO]") || aniName.Equals("[INTERROGACAO]") || aniName.Equals("[EXCLAMACAO]"))
545   - {
546   - playAnimation(TYPE_NONE, DEFAULT_ANIMATION, "", 1.6F);
547   - continue;
548   - }
549   -
550   - // Se já houve o soletramento de alguma palavra, reproduz animação default
551   - if (spelled)
552   - playAnimation(TYPE_NONE, DEFAULT_ANIMATION, lastAnimationSubtitle, 1.6F);
553   - else
554   - spelled = true;
555   -
556   - lastAnimationSubtitle = spellWord(aniName);
557   - }
558   - }
559   -
560   - // Default
561   - playAnimation(TYPE_NONE, DEFAULT_ANIMATION, "");
562   -
563   - loading = false;
564   - onPlayingStateChange();
565   - }
566   -
567   - //int _id = 0;
568   -
569   - /*
570   - * Sincroniza as legendas com as animações.
571   - */
572   - IEnumerator handleStates()
573   - {
574   - // Enquanto estiver executando a rotina "loadAndPlay"
575   - // ou existir animações na fila de reprodução
576   - while (loading || animQueue.Count > 0)
577   - {
578   - if (animQueue.Count > 0)
579   - {
580   - AnimationReference reference = animQueue.Peek();
581   -
582   - setSubtitle(reference.subtitle);
583   -
584   - while (COMPONENT_ANIMATION.IsPlaying(reference.name))
585   - {
586   - reference.playing = true;
587   - yield return null;
588   - }
589   -
590   - if (reference.state == null)
591   - animQueue.Dequeue();
592   - else
593   - yield return null;
594   - }
595   - else yield return null;
596   -
597   - setSubtitle("");
598   - }
599   -
600   - playing = false;
601   - paused = false;
602   - onPlayingStateChange();
603   - }
604   -
605   -}
Assets/Scripts/GenericPlayerManager.txt.meta
... ... @@ -1,8 +0,0 @@
1   -fileFormatVersion: 2
2   -guid: 8eb75e5e1bed9744c97d6ee131d4ab3b
3   -timeCreated: 1457721853
4   -licenseType: Pro
5   -TextScriptImporter:
6   - userData:
7   - assetBundleName:
8   - assetBundleVariant:
Assets/Scripts/Player Manager/GenericPlayerManager.cs
  1 +/** Gerenciador genérico e principal dos players.
  2 + *
  3 + * Versão 2.1
  4 + * - Acompanhamento da legenda
  5 + * Corrigido problema na soletração quando a velocidade ultrapassava ~1.
  6 + *
  7 + * Versão 2.2
  8 + * - Acompanhamento da legenda
  9 + * Corrigido problema na soletração quando o estado muda para pausado.
  10 + *
  11 + * Versão 2.3
  12 + * - Legenda
  13 + * A letras acentuadas reproduzem a mesma sem o acento.
  14 + *
  15 + * Versão 2.4
  16 + * - Legenda
  17 + * "Ç" reproduz "C".
  18 + * - Reprodução
  19 + * Quando não há acesso aos bundles dos sinais de pontuação, eles são ignorados.
  20 + * Ç adicionado como TYPE_WORD.
  21 + */
  22 +
1 23 //Log Dir http://docs.unity3d.com/Manual/LogFiles.html
2 24 using UnityEngine;
3 25 using System.Collections;
... ... @@ -14,7 +36,7 @@ public abstract class GenericPlayerManager : MonoBehaviour {
14 36 private const string DEFAULT_ANIMATION = "_default";
15 37 private const string DEFAULT_ANIMATION_MIDDLE = "_default_middle";
16 38  
17   - protected float fadeLength = 0.6F;
  39 + public float fadeLength = 0.6F;
18 40 public string gloss = "";
19 41  
20 42 // Referencia para o avatar
... ... @@ -22,7 +44,7 @@ public abstract class GenericPlayerManager : MonoBehaviour {
22 44 // Referencia para o componente animador do avatar
23 45 private Animation COMPONENT_ANIMATION;
24 46 public Text SUBTITLES;
25   -
  47 +
26 48 // Guarda os nomes das palavras já carregadas
27 49 private HashSet<string> loadedAssetBundles = new HashSet<string>();
28 50 // Guarda os nomes das palavras que não tem assetbundle
... ... @@ -46,12 +68,16 @@ public abstract class GenericPlayerManager : MonoBehaviour {
46 68  
47 69 // Se diferente de null, não está reproduzindo animação de intervalo
48 70 private AnimationState intervalAnimationState = null;
  71 + // Usado para pausar quando comandado
  72 + private AnimationReference animationPlaying = null;
49 73  
50 74 // Gerenciador de animações de intervalo
51 75 public RandomAnimations randomAnimations;
52 76 // Gerenciados de legendas
53 77 private Subtitle subtitles = null;
54 78  
  79 + private bool[] lastLetterAnimations = new bool[256];
  80 +
55 81 public virtual void Start()
56 82 {
57 83 // Configuração de velocidade das animações
... ... @@ -67,33 +93,33 @@ public abstract class GenericPlayerManager : MonoBehaviour {
67 93 // Sinais ignorados na legenda
68 94 string[] flags = new string[] {
69 95 "[PONTO]",
70   - "[INTERROGACAO]",
71   - "[EXCLAMACAO]"
  96 + "[INTERROGAÇÃO]",
  97 + "[EXCLAMAÇÃO]"
72 98 };
73 99 foreach (string flag in flags)
74 100 this.flags.Add(flag);
75 101  
76   - // Duplica sinais para diferenciar quando há repetidos
77   - string[] toDuplicate = new string[] {
78   - "A", "B", "C", "D", "E", "F", "G", "H", "I",
  102 + string[] preloadedAnims = new string[] {
  103 + "A", "B", "C", "Ç", "D", "E", "F", "G", "H", "I",
79 104 "J", "K", "L", "M", "N", "O", "P", "Q", "R",
80 105 "S", "T", "U", "V", "W", "X", "Y", "Z",
81   - "0", "1", "2", "3", "4",
82   - "5", "6", "7", "8", "9",
83   - ","
  106 + "0", "1", "2", "3", "4",
  107 + "5", "6", "7", "8", "9",
  108 + ","
84 109 };
85   - foreach (string anim in toDuplicate)
  110 +
  111 + // Duplica sinais para diferenciar quando há repetidos
  112 + foreach (string anim in preloadedAnims)
86 113 COMPONENT_ANIMATION.AddClip(COMPONENT_ANIMATION[anim].clip, "d_" + anim);
87 114  
88   - // Sinal default é tratado como animação de intervalo: não sinaliza reprodução na UI
89   - //this.intervalAnimations.Add(DEFAULT_ANIMATION);
  115 + foreach (string anim in preloadedAnims)
  116 + this.loadedAssetBundles.Add(anim);
90 117  
91 118 // Cria novo _default chamado _default_middle para pausas dentro de uma glosa
92 119 // Impede que a animação default seja confundida com não-reprodução na UI
93 120 COMPONENT_ANIMATION.AddClip(COMPONENT_ANIMATION[DEFAULT_ANIMATION].clip, DEFAULT_ANIMATION_MIDDLE);
94 121 }
95 122  
96   - /* Estados */
97 123 public bool isPlayingIntervalAnimation() { return intervalAnimationState != null; }
98 124 public bool isLoading() { return loading; }
99 125 public bool isPlaying() { return playing; }
... ... @@ -125,9 +151,9 @@ public abstract class GenericPlayerManager : MonoBehaviour {
125 151 subtitles.updateNumberSpeed();
126 152  
127 153 // Altera a velocidade de todas as animações em reprodução
128   - if ( ! paused) lock (animQueue)
  154 + if ( ! paused) lock (this.animQueue)
129 155 {
130   - foreach (AnimationReference reference in animQueue)
  156 + foreach (AnimationReference reference in this.animQueue)
131 157 if (reference.type != Subtitle.TYPE_NONE && reference.state != null)
132 158 reference.state.speed = getSpeedByType(reference.type);
133 159 }
... ... @@ -142,7 +168,7 @@ public abstract class GenericPlayerManager : MonoBehaviour {
142 168 case Subtitle.TYPE_LETTER: return subtitles.LetterSpeed;
143 169 case Subtitle.TYPE_NUMBER: return subtitles.NumberSpeed;
144 170 }
145   -
  171 +
146 172 return 2F;
147 173 }
148 174  
... ... @@ -163,12 +189,10 @@ public abstract class GenericPlayerManager : MonoBehaviour {
163 189 this.randomAnimations.unlockFor("handleStates");
164 190 this.subtitles.setText("");
165 191  
166   - lock (animQueue) { animQueue.Clear(); }
  192 + lock (this.animQueue) { this.animQueue.Clear(); }
167 193 COMPONENT_ANIMATION.CrossFadeQueued(DEFAULT_ANIMATION, fadeLength, QueueMode.PlayNow);
168   -
169   - playing = false;
170   - paused = false;
171   - onPlayingStateChange();
  194 +
  195 + resetStates();
172 196 }
173 197  
174 198 /* Repete animações */
... ... @@ -192,7 +216,7 @@ public abstract class GenericPlayerManager : MonoBehaviour {
192 216 state.speed = speed;
193 217  
194 218 lock (this.animQueue) {
195   - animQueue.Enqueue(new AnimationReference(name, subtitle, state, type));
  219 + this.animQueue.Enqueue(new AnimationReference(name, subtitle, state, type));
196 220 }
197 221  
198 222 return state;
... ... @@ -229,12 +253,17 @@ public abstract class GenericPlayerManager : MonoBehaviour {
229 253 */
230 254 public abstract WWW loadAssetBundle(string aniName);
231 255  
  256 + /**
  257 + * Listen to changes in the playing status.
  258 + */
  259 + public abstract void onConnectionError(string gloss, string word);
232 260  
233 261 /**
234 262 * Listen to changes in the playing status.
235 263 */
236 264 public abstract void onPlayingStateChange();
237 265  
  266 +
238 267 /* Pause or continue animations */
239 268 public void setPauseState(bool paused)
240 269 {
... ... @@ -242,15 +271,22 @@ public abstract class GenericPlayerManager : MonoBehaviour {
242 271 {
243 272 this.paused = paused;
244 273  
245   - lock (animQueue)
  274 + lock (this.animQueue)
246 275 {
247   - foreach (AnimationReference reference in animQueue)
  276 + if (this.animationPlaying != null && this.animationPlaying.state != null)
  277 + this.animationPlaying.state.speed = paused ? 0F : getSpeedByType(this.animationPlaying.type);
  278 +
  279 + foreach (AnimationReference reference in this.animQueue)
248 280 if (reference.state != null)
249 281 reference.state.speed = paused ? 0F : getSpeedByType(reference.type);
250 282 }
251   -
252   - onPlayingStateChange();
253 283 }
  284 +
  285 + onPlayingStateChange();
  286 + }
  287 +
  288 + public void setAnimationEnabled(bool enabled) {
  289 + COMPONENT_ANIMATION.enabled = enabled;
254 290 }
255 291  
256 292 /* Pause or continue animations */
... ... @@ -309,6 +345,32 @@ public abstract class GenericPlayerManager : MonoBehaviour {
309 345 return true;
310 346 }
311 347  
  348 + private string nextLetterAnimation(char letter)
  349 + {
  350 + string animation = (this.lastLetterAnimations[letter] ? "" : "d_") + letter.ToString();
  351 + this.lastLetterAnimations[letter] = ! this.lastLetterAnimations[letter];
  352 +
  353 + return animation;
  354 + }
  355 +
  356 + private static short getType(char c)
  357 + {
  358 + // Se for uma letra
  359 + if (c >= 65 && c <= 90)
  360 + return Subtitle.TYPE_LETTER;
  361 +
  362 + // Se for um número
  363 + else if (c >= 48 && c <= 57)
  364 + return Subtitle.TYPE_NUMBER;
  365 +
  366 + // Se for uma vírgula
  367 + else if (c == 44 || c == 'Ç')
  368 + return Subtitle.TYPE_WORD;
  369 +
  370 + else
  371 + return Subtitle.TYPE_NONE;
  372 + }
  373 +
312 374 /* Enfileira soletração de palavra */
313 375 private string spellWord(Queue<ToPlay> toPlayQueue, string word)
314 376 {
... ... @@ -318,50 +380,56 @@ public abstract class GenericPlayerManager : MonoBehaviour {
318 380 // A reprodução da primeira letra deve ser longa para não ser cortada no fade
319 381 this.subtitles.updateLetterSpeed();
320 382  
321   - string lastAnim = "";
322   -
323 383 for (int i = 0; i < word.Length; i++)
324 384 {
325 385 lastAnimationSubtitle = Subtitle.highlight(word, i);
  386 + char anim = word[i];
326 387  
327   - string anim = word[i].ToString();
328   - lastAnim = anim.Equals(lastAnim) ? "d_" + anim : anim;
329   -
330   - short type;
331   -
332   - // Se for uma letra
333   - if (word[i] >= 65 && word[i] <= 90)
334   - type = Subtitle.TYPE_LETTER;
335   -
336   - // Se for um número
337   - else if (word[i] >= 48 && word[i] <= 57)
338   - type = Subtitle.TYPE_NUMBER;
  388 + switch (word[i])
  389 + {
  390 + case 'Á':
  391 + case 'Â':
  392 + case 'À':
  393 + case 'Ã': anim = 'A';
  394 + break;
  395 + case 'É':
  396 + case 'Ê': anim = 'E';
  397 + break;
  398 + case 'Í': anim = 'I';
  399 + break;
  400 + case 'Ó':
  401 + case 'Ô':
  402 + case 'Õ': anim = 'O';
  403 + break;
  404 + case 'Ú': anim = 'U';
  405 + break;
  406 + }
339 407  
340   - // Se for uma vírgula
341   - else if (word[i] == 44)
342   - type = Subtitle.TYPE_WORD;
  408 + short type = getType(anim);
  409 + string animName = nextLetterAnimation(anim);
343 410  
344 411 // Não há animação
345   - else
  412 + if (type == Subtitle.TYPE_NONE)
346 413 {
347 414 // Reproduz animação default apenas uma vez
348 415 if ( ! defaultPlayed)
349 416 {
350 417 defaultPlayed = true;
351   - toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_NONE, DEFAULT_ANIMATION_MIDDLE, lastAnimationSubtitle, this));
  418 + toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_WORD, DEFAULT_ANIMATION_MIDDLE, lastAnimationSubtitle, this));
352 419  
353 420 // A reprodução da próxima letra deve ser longa para não ser cortada no fade
354 421 this.subtitles.updateLetterSpeed();
355 422 }
356 423  
357   - UnityEngine.Debug.Log("Animação \"" + word[i] + "\" inexistente.");
358   - continue;
  424 + UnityEngine.Debug.Log("Animação \"" + animName + "\" inexistente.");
359 425 }
360   -
361   - toPlayQueue.Enqueue(new ToPlay(type, lastAnim, lastAnimationSubtitle, this));
  426 + else
  427 + {
  428 + toPlayQueue.Enqueue(new ToPlay(type, animName, lastAnimationSubtitle, this));
362 429  
363   - defaultPlayed = false;
364   - this.subtitles.updateLetterSpeed();
  430 + defaultPlayed = false;
  431 + this.subtitles.updateLetterSpeed();
  432 + }
365 433 }
366 434  
367 435 return lastAnimationSubtitle;
... ... @@ -403,7 +471,7 @@ public abstract class GenericPlayerManager : MonoBehaviour {
403 471 {
404 472 this.randomAnimations.lockFor("loadAndPlay");
405 473 this.loading = true;
406   - onPlayingStateChange();
  474 + // onPlayingStateChange();
407 475  
408 476 string lastAnimationSubtitle = "";
409 477 bool spelled = false;
... ... @@ -437,23 +505,29 @@ public abstract class GenericPlayerManager : MonoBehaviour {
437 505 AssetBundle bundle = null;
438 506  
439 507 if (www.error == null)
440   - bundle = www.assetBundle;
441   -
442   - if (bundle != null && ! String.IsNullOrEmpty(bundle.mainAsset.name))
443 508 {
444   - AnimationClip aniClip = bundle.mainAsset as AnimationClip;
445   - bundle.Unload(false);
  509 + bundle = www.assetBundle;
446 510  
447   - if (aniClip)
  511 + if (bundle != null && ! String.IsNullOrEmpty(bundle.mainAsset.name))
448 512 {
449   - COMPONENT_ANIMATION.AddClip(aniClip, aniName);
  513 + AnimationClip aniClip = bundle.mainAsset as AnimationClip;
  514 + bundle.Unload(false);
450 515  
451   - loadedAssetBundles.Add(aniName);
452   - loaded = true;
  516 + if (aniClip)
  517 + {
  518 + COMPONENT_ANIMATION.AddClip(aniClip, aniName);
  519 +
  520 + loadedAssetBundles.Add(aniName);
  521 + loaded = true;
  522 +
  523 + Debug.Log("Bundle \"" + aniName + "\" loaded!");
  524 + }
  525 + else UnityEngine.Debug.Log ("Sinal \"" + aniName + "\" foi não carregado corretamente.");
453 526 }
454   - else UnityEngine.Debug.Log ("Sinal \"" + aniName + "\" não carregado corretamente.");
455 527 }
  528 + else onConnectionError(gloss, aniName);
456 529 }
  530 + else onConnectionError(gloss, aniName);
457 531 }
458 532  
459 533 // Reproduz palavra
... ... @@ -490,20 +564,21 @@ public abstract class GenericPlayerManager : MonoBehaviour {
490 564  
491 565 if (this.flags.Contains(aniName) || this.intervalAnimations.Contains(aniName))
492 566 {
493   - //playAnimation(Subtitle.TYPE_NONE, DEFAULT_ANIMATION, "", 1.6F);
494 567 toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_NONE, DEFAULT_ANIMATION_MIDDLE, "", 1.6F));
495   - continue;
  568 + spelled = false;
496 569 }
497   -
498   - // Se já houve o soletramento de alguma palavra, reproduz animação default
499   - if (spelled)
500   - toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_NONE, DEFAULT_ANIMATION_MIDDLE, lastAnimationSubtitle, 1.6F));
501 570 else
502   - spelled = true;
  571 + {
  572 + // Se já houve o soletramento de alguma palavra, reproduz animação default
  573 + if (spelled)
  574 + toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_NONE, DEFAULT_ANIMATION_MIDDLE, "", 1.6F));
  575 + else
  576 + spelled = true;
503 577  
504   - lastAnimationSubtitle = spellWord(toPlayQueue, aniName);
  578 + lastAnimationSubtitle = spellWord(toPlayQueue, aniName);
  579 + }
505 580 }
506   -
  581 +
507 582 if (toPlayQueue.Count > 4 || wordsCount == stringPos.Length)
508 583 while (toPlayQueue.Count > 0)
509 584 toPlayQueue.Dequeue().play(this);
... ... @@ -513,7 +588,7 @@ public abstract class GenericPlayerManager : MonoBehaviour {
513 588 playAnimation(Subtitle.TYPE_NONE, DEFAULT_ANIMATION, "");
514 589  
515 590 this.loading = false;
516   - onPlayingStateChange();
  591 + // onPlayingStateChange();
517 592 this.randomAnimations.unlockFor("loadAndPlay");
518 593 }
519 594 }
... ... @@ -530,43 +605,93 @@ public abstract class GenericPlayerManager : MonoBehaviour {
530 605 onPlayingStateChange();
531 606  
532 607 bool isNotEmpty;
533   - lock (animQueue) { isNotEmpty = animQueue.Count > 0; }
  608 + lock (this.animQueue) { isNotEmpty = this.animQueue.Count > 0; }
  609 +
  610 + // Animação anterior a atual
  611 + AnimationReference endedAnimation = null;
534 612  
535   - // Enquanto estiver executando a rotina "loadAndPlay"
  613 + // Enquanto estiver executando a corotina "loadAndPlay"
536 614 // ou existir animações na fila de reprodução
537 615 while (loading || isNotEmpty)
538 616 {
  617 + // Se não houver animações na fila, espera
539 618 if (isNotEmpty)
540 619 {
  620 + // Pega primeira animação
541 621 AnimationReference reference;
542   - lock (animQueue) { reference = animQueue.Peek(); }
543   -
544   - this.subtitles.setText(reference.subtitle);
  622 + lock (this.animQueue) { reference = this.animQueue.Peek(); }
545 623  
  624 + // Se estiver sendo reproduzida
546 625 if (COMPONENT_ANIMATION.IsPlaying(reference.name))
547 626 {
548   - do { yield return null; }
549   - while (COMPONENT_ANIMATION.IsPlaying(reference.name));
  627 + this.subtitles.setText(reference.subtitle);
  628 +
  629 + // Animação seguinte
  630 + AnimationReference next = null;
  631 + lock (this.animQueue)
  632 + {
  633 + this.animationPlaying = this.animQueue.Dequeue();
  634 +
  635 + if (this.animQueue.Count > 0)
  636 + next = this.animQueue.Peek();
  637 + }
  638 +
  639 + while (true)
  640 + {
  641 + // Se a próxima animação estiver sendo reproduzida (no fade)
  642 + if (next != null && COMPONENT_ANIMATION.IsPlaying(next.name))
  643 + {
  644 + // Se a animação anterior a atual não tiver acabado,
  645 + // espera acabar e só então conta o tempo
  646 + if (endedAnimation != null)
  647 + while (COMPONENT_ANIMATION.IsPlaying(endedAnimation.name))
  648 + yield return null;
  649 +
  650 + // Tempo para pular para a legenda da próxima animação
  651 + yield return new WaitForSeconds(0.4F);
  652 +
  653 + // Deprecated
  654 + // yield return WaitForContinuousMillis.Wait(this, 300);
  655 +
  656 + endedAnimation = reference;
  657 + break;
  658 + }
  659 +
  660 + else if (COMPONENT_ANIMATION.IsPlaying(reference.name))
  661 + yield return null;
  662 +
  663 + else break;
  664 + }
  665 +
  666 + reference = null;
550 667 }
551 668  
552   - if (reference.state == null)
553   - lock (animQueue) { animQueue.Dequeue(); }
  669 + // Se a animação não tiver sido liberada e seu AnimationState for nulo,
  670 + // a animação será liberada
  671 + if (reference != null && reference.state == null)
  672 + lock (this.animQueue) { this.animQueue.Dequeue(); }
554 673 else
555 674 yield return null;
556 675 }
557 676 else yield return null;
558 677  
559   - this.subtitles.setText("");
560   -
561   - lock (animQueue) { isNotEmpty = animQueue.Count > 0; }
  678 + lock (this.animQueue) { isNotEmpty = this.animQueue.Count > 0; }
562 679 }
563 680  
564   - this.playing = false;
565   - this.paused = false;
566   - onPlayingStateChange();
  681 + this.subtitles.setText("");
567 682  
  683 + resetStates();
568 684 this.randomAnimations.unlockFor("handleStates");
569 685 }
570 686 }
571 687  
  688 + public void resetStates()
  689 + {
  690 + this.animationPlaying = null;
  691 + this.playing = false;
  692 + this.paused = false;
  693 +
  694 + onPlayingStateChange();
  695 + }
  696 +
572 697 }
... ...
Assets/Scripts/Player Manager/RandomAnimations.cs
... ... @@ -60,36 +60,37 @@ public class RandomAnimations : MonoBehaviour {
60 60 {
61 61 while (true)
62 62 {
63   - while (this.playerManager.isPlayingIntervalAnimation())
64   - yield return new WaitForSeconds(1);
  63 + // Espera enquanto estiver reproduzindo animações de intervalo
  64 + do { yield return null; }
  65 + while (this.playerManager.isPlayingIntervalAnimation());
65 66  
66   - bool isNotBlocked;
67   - lock (this.blockingObjects) {
68   - isNotBlocked = this.blockingObjects.Count == 0;
69   - }
70   -
71   - if (isNotBlocked)
  67 + // Se houver bloqueio, espera acabar
  68 + while (true)
72 69 {
73   - yield return new WaitForSeconds(this.time);
74   -
75 70 lock (this.blockingObjects) {
76   - if (this.blockingObjects.Count > 0)
77   - continue;
  71 + if (this.blockingObjects.Count == 0)
  72 + break;
78 73 }
79 74  
80   - int index = sortIndex();
  75 + yield return null;
  76 + }
81 77  
82   - if (index != -1)
83   - {
84   - if (index == this.lastIndex)
85   - index = sortIndex();
  78 + // Espera time
  79 + yield return new WaitForSeconds(this.time);
86 80  
87   - //this.playerManager.play(this.names[index], true, false, true);
88   - this.playerManager.playIntervalAnimation(this.names[index]);
89   - }
  81 + // Se houver bloqueio, volta a esperar
  82 + lock (this.blockingObjects) {
  83 + if (this.blockingObjects.Count > 0)
  84 + continue;
90 85 }
91   -
92   - yield return null;
  86 +
  87 + int index = sortIndex();
  88 +
  89 + if (index != -1 && index == this.lastIndex)
  90 + index = sortIndex();
  91 +
  92 + if (index != -1)
  93 + this.playerManager.playIntervalAnimation(this.names[index]);
93 94 }
94 95 }
95 96  
... ...
Assets/Scripts/Player Manager/Subtitle.cs
... ... @@ -2,6 +2,12 @@ using UnityEngine.UI;
2 2  
3 3 /**
4 4 * Gerenciador de legendas
  5 + *
  6 + * Versão 1.1
  7 + * - Caracteres de letras acentuadas e % são separados com "-".
  8 + *
  9 + * Versão 1.1.1
  10 + * - "Ç" é separada por "-" na legenda.
5 11 */
6 12 public class Subtitle {
7 13  
... ... @@ -32,7 +38,7 @@ public class Subtitle {
32 38 private float numberSpeed = DefaultSignSpeed.DEFAULT;
33 39  
34 40 public static string highlightedColor = "white";
35   -
  41 +
36 42 // Referência para a legenda
37 43 public Text subtitle;
38 44  
... ... @@ -116,6 +122,28 @@ public class Subtitle {
116 122 this.NumberSpeed = this.DefaultNumberSpeed.getProportional(this.SliderPosition);
117 123 }
118 124  
  125 + public static bool isSeparable(char c)
  126 + {
  127 + switch (c)
  128 + {
  129 + case '%':
  130 + case 'Á':
  131 + case 'Â':
  132 + case 'À':
  133 + case 'Ã':
  134 + case 'É':
  135 + case 'Ê':
  136 + case 'Í':
  137 + case 'Ó':
  138 + case 'Ô':
  139 + case 'Õ':
  140 + case 'Ú':
  141 + case 'Ç': return true;
  142 + }
  143 +
  144 + return (c >= 65 && c <= 90) || (c >= 48 && c <= 57);
  145 + }
  146 +
119 147 /* Destaca caractere de uma string. */
120 148 public static string highlight(string word, int index)
121 149 {
... ... @@ -123,7 +151,7 @@ public class Subtitle {
123 151  
124 152 for (int i = 0; i < word.Length; i++)
125 153 {
126   - if (i > 0 && ((word[i] >= 65 && word[i] <= 90) || (word[i] >= 48 && word[i] <= 57)))
  154 + if (i > 0 && isSeparable(word[i]))
127 155 subtitle += "-";
128 156  
129 157 if (i == index)
... ...
Assets/Scripts/PlayerManager.cs
... ... @@ -22,15 +22,11 @@ public class PlayerManager : GenericPlayerManager {
22 22  
23 23 public override void Start()
24 24 {
25   - //base.defaultFirstLetterSpeed = new DefaultSignSpeed(2.3F, 3.2F);
26   - //base.defaultLetterSpeed = new DefaultSignSpeed(3.1F, 4.6F);
27   -
28 25 base.Start();
29 26 Application.ExternalCall("onLoadPlayer");
30 27 }
31 28  
32 29 // SendMessage("PlayerManager", "catchGlosa", "LAVID");
33   - // SendMessage("PlayerManager", "switchSubtitleStatus");
34 30  
35 31 public override WWW loadAssetBundle(string aniName) {
36 32 return WWW.LoadFromCacheOrDownload(BASE_URL + aniName, 1);
... ... @@ -46,6 +42,8 @@ public class PlayerManager : GenericPlayerManager {
46 42 base.isRepeatable());
47 43 }
48 44  
  45 + public override void onConnectionError(string gloss, string word) { }
  46 +
49 47 private static bool itb(int value) {
50 48 return value == 0 ? false : true;
51 49 }
... ...
ProjectSettings/ProjectSettings.asset
... ... @@ -477,7 +477,7 @@ PlayerSettings:
477 477 - WebGL::useEmbeddedResources
478 478 - XboxOne::enus
479 479 WebGL::analyzeBuildSize: 0
480   - WebGL::dataCaching: 1
  480 + WebGL::dataCaching: 0
481 481 WebGL::useEmbeddedResources: 0
482 482 XboxOne::enus: 1
483 483 stringPropertyNames:
... ...