/plugins/Radegast.Plugin.Speech/RadSpeech/Environment/People.cs

https://bitbucket.org/FlyMan/radegast · C# · 183 lines · 119 code · 28 blank · 36 comment · 8 complexity · 568abeab0a830f613977984bc0d940e0 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Radegast;
  6. using OpenMetaverse;
  7. namespace RadegastSpeech.Environment
  8. {
  9. /// <summary>
  10. /// Keep track of other avatars
  11. /// </summary>
  12. class People
  13. {
  14. private PluginControl control;
  15. private Talk.Control Talker { get { return control.talker; } }
  16. private GridClient Client { get { return control.instance.Client; } }
  17. private Dictionary<UUID, AvatarInfo> information;
  18. private readonly string[] genders;
  19. private Random random;
  20. private readonly string[] directions;
  21. private readonly double sectorsize;
  22. internal People(PluginControl pc)
  23. {
  24. control = pc;
  25. information = new Dictionary<UUID,AvatarInfo>();
  26. genders = new string[]{"female","male"};
  27. // Directions are in a few equal-sized sectors
  28. directions = new string[]
  29. { "to your right",
  30. "in front of you",
  31. "to your left",
  32. "behind you" };
  33. sectorsize = Math.PI * 2.0 / (double)directions.Length;
  34. }
  35. internal void Start()
  36. {
  37. // We need appearance info about people
  38. Client.Avatars.AvatarAppearance +=
  39. new EventHandler<AvatarAppearanceEventArgs>(Avatars_OnAvatarAppearance);
  40. }
  41. internal void Shutdown()
  42. {
  43. Client.Avatars.AvatarAppearance -=
  44. new EventHandler<AvatarAppearanceEventArgs>(Avatars_OnAvatarAppearance);
  45. information.Clear();
  46. }
  47. /// <summary>
  48. /// Save information about an avatar's appearance
  49. /// </summary>
  50. /// <param name="avatarID"></param>
  51. /// <param name="isTrial"></param>
  52. /// <param name="defaultTexture"></param>
  53. /// <param name="faceTextures"></param>
  54. /// <param name="visualParams"></param>
  55. void Avatars_OnAvatarAppearance(
  56. object sender,
  57. AvatarAppearanceEventArgs e)
  58. {
  59. List<byte> visualParams = e.VisualParams;
  60. // Create an entry in the avatar information dictionary.
  61. if (visualParams.Count > 32)
  62. {
  63. AvatarInfo info = new AvatarInfo();
  64. info.gender = visualParams[31];
  65. info.height = visualParams[32];
  66. // We are only getting 218 parameters.
  67. // info.leglen = visualParams[691];
  68. information[e.AvatarID] = info;
  69. // Check if a wrong voice has already been assigned, and reassign
  70. // if necessary.
  71. Talker.voices.CheckGender(e.AvatarID, info);
  72. }
  73. }
  74. /// <summary>
  75. /// Report the gender of an avatar.
  76. /// </summary>
  77. /// <param name="id"></param>
  78. /// <returns></returns>
  79. internal bool isMale(UUID id)
  80. {
  81. if (information.ContainsKey(id))
  82. return (information[id].gender>0);
  83. // No information, so make a random guess.
  84. if (random == null)
  85. random = new Random();
  86. return (random.Next(10) > 4); // 50/50 odds
  87. }
  88. private double Heading(Vector3 place)
  89. {
  90. Vector3 v3 = Vector3.Transform(
  91. Vector3.UnitX,
  92. Matrix4.CreateFromQuaternion(Client.Self.Movement.BodyRotation));
  93. return Math.Atan2( -v3.X, -v3.Y ) + Math.PI;
  94. }
  95. /// <summary>
  96. /// Verbally describe a distance and direction
  97. /// </summary>
  98. /// <param name="theirpos"></param>
  99. /// <returns></returns>
  100. internal string Location(Vector3 theirpos)
  101. {
  102. if (theirpos == Vector3.Zero)
  103. return string.Empty;
  104. AgentManager my = control.instance.Client.Self;
  105. // Get the vector to the object, and distance.
  106. Vector3 difference = theirpos - my.SimPosition;
  107. float dist = difference.Length();
  108. // Rotate the vector opposite to our body rotation.
  109. Vector3 faceRelative = Vector3.Transform(
  110. difference,
  111. Matrix4.CreateFromQuaternion(my.Movement.BodyRotation));
  112. double bearing = Math.Atan2( faceRelative.Y, faceRelative.X ) + Math.PI;
  113. // Pick which sector that is in.
  114. int sector = (int)(bearing / sectorsize);
  115. return string.Format(", {0:0} meters {1}", dist, directions[sector]);
  116. }
  117. internal Vector3 SameDirection(Vector3 theirpos)
  118. {
  119. AgentManager my = control.instance.Client.Self;
  120. // Get the vector to the object, and distance.
  121. Vector3 difference = theirpos - my.SimPosition;
  122. // Make a 4m vector in the same direction.
  123. Vector3 pointer = Vector3.Multiply(
  124. Vector3.Normalize( difference ), 4.0f );
  125. // Add my position back
  126. pointer += my.SimPosition;
  127. return pointer;
  128. }
  129. internal string Describe(UUID id)
  130. {
  131. if (!information.ContainsKey(id))
  132. {
  133. return null;
  134. }
  135. AvatarInfo info = information[id];
  136. string shape = genders[info.gender > 0 ? 1 : 0];
  137. // Add height unless it looks wrong.
  138. #if NOT
  139. if (info.height > 0)
  140. {
  141. double height = -2.3 + (((2.0 - -2.3) / 256) * info.height);
  142. double legs = -1.0 + (((1.0 - -1.0) / 256) * info.leglen);
  143. shape += string.Format(" and {1:0.#} meters tall.",
  144. heights);
  145. }
  146. #endif
  147. return shape;
  148. }
  149. public struct AvatarInfo
  150. {
  151. public byte gender;
  152. public byte height;
  153. }
  154. }
  155. }