aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Framework/AvatarAppearance.cs11
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs219
2 files changed, 171 insertions, 59 deletions
diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index 05330c7..e66a1e7 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -233,7 +233,7 @@ namespace OpenSim.Framework
233// DEBUG ON 233// DEBUG ON
234 m_log.WarnFormat("[AVATAR APPEARANCE] create empty appearance for {0}",owner); 234 m_log.WarnFormat("[AVATAR APPEARANCE] create empty appearance for {0}",owner);
235// DEBUG OFF 235// DEBUG OFF
236 m_serial = 0; 236 m_serial = 1;
237 m_owner = owner; 237 m_owner = owner;
238 238
239 SetDefaultWearables(); 239 SetDefaultWearables();
@@ -289,7 +289,7 @@ namespace OpenSim.Framework
289// DEBUG OFF 289// DEBUG OFF
290 if (appearance == null) 290 if (appearance == null)
291 { 291 {
292 m_serial = 0; 292 m_serial = 1;
293 m_owner = UUID.Zero; 293 m_owner = UUID.Zero;
294 294
295 SetDefaultWearables(); 295 SetDefaultWearables();
@@ -467,6 +467,9 @@ namespace OpenSim.Framework
467 public override String ToString() 467 public override String ToString()
468 { 468 {
469 String s = ""; 469 String s = "";
470
471 s += String.Format("Serial: {0}\n",m_serial);
472
470 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) 473 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
471 if (m_texture.FaceTextures[i] != null) 474 if (m_texture.FaceTextures[i] != null)
472 s += String.Format("Texture: {0} --> {1}\n",i,m_texture.FaceTextures[i].TextureID); 475 s += String.Format("Texture: {0} --> {1}\n",i,m_texture.FaceTextures[i].TextureID);
@@ -625,8 +628,8 @@ namespace OpenSim.Framework
625 /// </summary> 628 /// </summary>
626 public void Unpack(OSDMap data) 629 public void Unpack(OSDMap data)
627 { 630 {
628 if ((data != null) && (data["appearance_serial"] != null)) 631 if ((data != null) && (data["serial"] != null))
629 m_serial = data["appearance_serial"].AsInteger(); 632 m_serial = data["serial"].AsInteger();
630 if ((data != null) && (data["height"] != null)) 633 if ((data != null) && (data["height"] != null))
631 m_avatarHeight = (float)data["height"].AsReal(); 634 m_avatarHeight = (float)data["height"].AsReal();
632 if ((data != null) && (data["hipoffset"] != null)) 635 if ((data != null) && (data["hipoffset"] != null))
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 5444f80..903e94b 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -32,6 +32,10 @@ using Nini.Config;
32using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Framework; 33using OpenSim.Framework;
34 34
35using System.Threading;
36using System.Timers;
37using System.Collections.Generic;
38
35using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
37using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
@@ -44,7 +48,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
44 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; 48 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
45 private Scene m_scene = null; 49 private Scene m_scene = null;
46 50
47 private bool m_startAnimationSet = false; 51 private static readonly int m_savetime = 5; // seconds to wait before saving changed appearance
52 private static readonly int m_sendtime = 2; // seconds to wait before sending changed appearance
53
54 private static readonly int m_checkTime = 500; // milliseconds to wait between checks for appearance updates
55 private System.Timers.Timer m_updateTimer = new System.Timers.Timer();
56 private Dictionary<UUID,long> m_savequeue = new Dictionary<UUID,long>();
57 private Dictionary<UUID,long> m_sendqueue = new Dictionary<UUID,long>();
58
59 #region RegionModule Members
48 60
49 public void Initialise(Scene scene, IConfigSource source) 61 public void Initialise(Scene scene, IConfigSource source)
50 { 62 {
@@ -56,6 +68,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
56 68
57 public void PostInitialise() 69 public void PostInitialise()
58 { 70 {
71 m_updateTimer.Enabled = false;
72 m_updateTimer.AutoReset = true;
73 m_updateTimer.Interval = m_checkTime; // 500 milliseconds wait to start async ops
74 m_updateTimer.Elapsed += new ElapsedEventHandler(HandleAppearanceUpdateTimer);
59 } 75 }
60 76
61 public void Close() 77 public void Close()
@@ -84,15 +100,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
84 // client.OnAvatarNowWearing -= AvatarIsWearing; 100 // client.OnAvatarNowWearing -= AvatarIsWearing;
85 } 101 }
86 102
87 public void CheckBakedTextureAssets(IClientAPI client, UUID textureID, int idx) 103 #endregion
88 { 104
89 if (m_scene.AssetService.Get(textureID.ToString()) == null)
90 {
91 m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",textureID,idx,client.Name);
92 client.SendRebakeAvatarTextures(textureID);
93 }
94 }
95
96 /// <summary> 105 /// <summary>
97 /// Set appearance data (textureentry and slider settings) received from the client 106 /// Set appearance data (textureentry and slider settings) received from the client
98 /// </summary> 107 /// </summary>
@@ -100,6 +109,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
100 /// <param name="visualParam"></param> 109 /// <param name="visualParam"></param>
101 public void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams) 110 public void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams)
102 { 111 {
112// DEBUG ON
113 m_log.WarnFormat("[AVFACTORY] SetAppearance for {0}",client.AgentId);
114// DEBUG OFF
115
103 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 116 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
104 if (sp == null) 117 if (sp == null)
105 { 118 {
@@ -107,79 +120,175 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
107 return; 120 return;
108 } 121 }
109 122
110// DEBUG ON
111 m_log.WarnFormat("[AVFACTORY] SetAppearance for {0}",client.AgentId);
112// DEBUG OFF
113
114/*
115 if (m_physicsActor != null)
116 {
117 if (!IsChildAgent)
118 {
119 // This may seem like it's redundant, remove the avatar from the physics scene
120 // just to add it back again, but it saves us from having to update
121 // 3 variables 10 times a second.
122 bool flyingTemp = m_physicsActor.Flying;
123 RemoveFromPhysicalScene();
124 //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
125
126 //PhysicsActor = null;
127
128 AddToPhysicalScene(flyingTemp);
129 }
130 }
131*/
132 #region Bake Cache Check
133
134 bool changed = false; 123 bool changed = false;
135 124
136 // Process the texture entry 125 // Process the texture entry
137 if (textureEntry != null) 126 if (textureEntry != null)
138 { 127 {
128 changed = sp.Appearance.SetTextureEntries(textureEntry);
129
139 for (int i = 0; i < BAKE_INDICES.Length; i++) 130 for (int i = 0; i < BAKE_INDICES.Length; i++)
140 { 131 {
141 int j = BAKE_INDICES[i]; 132 int idx = BAKE_INDICES[i];
142 Primitive.TextureEntryFace face = textureEntry.FaceTextures[j]; 133 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
143
144 if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) 134 if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
145 Util.FireAndForget(delegate(object o) { CheckBakedTextureAssets(client,face.TextureID,j); }); 135 Util.FireAndForget(delegate(object o) { CheckBakedTextureAssets(client,face.TextureID,idx); });
146 } 136 }
147 changed = sp.Appearance.SetTextureEntries(textureEntry);
148
149 } 137 }
150 138
151 #endregion Bake Cache Check 139 // Process the visual params, this may change height as well
152 140 if (visualParams != null)
153 changed = sp.Appearance.SetVisualParams(visualParams) || changed; 141 {
154 142 if (sp.Appearance.SetVisualParams(visualParams))
155 // If nothing changed (this happens frequently) just return 143 {
144 changed = true;
145 if (sp.Appearance.AvatarHeight > 0)
146 sp.SetHeight(sp.Appearance.AvatarHeight);
147 }
148 }
149
150 // If something changed in the appearance then queue an appearance save
156 if (changed) 151 if (changed)
152 QueueAppearanceSave(client.AgentId);
153
154 // And always queue up an appearance update to send out
155 QueueAppearanceSend(client.AgentId);
156
157 // Send the appearance back to the avatar
158 AvatarAppearance avp = sp.Appearance;
159 sp.ControllingClient.SendAvatarDataImmediate(sp);
160 sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes());
161 }
162
163 /// <summary>
164 /// Checks for the existance of a baked texture asset and
165 /// requests the viewer rebake if the asset is not found
166 /// </summary>
167 /// <param name="client"></param>
168 /// <param name="textureID"></param>
169 /// <param name="idx"></param>
170 private void CheckBakedTextureAssets(IClientAPI client, UUID textureID, int idx)
171 {
172 if (m_scene.AssetService.Get(textureID.ToString()) == null)
173 {
174 m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",
175 textureID,idx,client.Name);
176 client.SendRebakeAvatarTextures(textureID);
177 }
178 }
179
180 #region UpdateAppearanceTimer
181
182 public void QueueAppearanceSend(UUID agentid)
183 {
184// DEBUG ON
185 m_log.WarnFormat("[AVFACTORY] Queue appearance send for {0}",agentid);
186// DEBUG OFF
187
188 // 100 nanoseconds (ticks) we should wait
189 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 10000000);
190 lock (m_sendqueue)
157 { 191 {
192 m_sendqueue[agentid] = timestamp;
193 m_updateTimer.Start();
194 }
195 }
196
197 public void QueueAppearanceSave(UUID agentid)
198 {
158// DEBUG ON 199// DEBUG ON
159 m_log.Warn("[AVFACTORY] Appearance changed"); 200 m_log.WarnFormat("[AVFACTORY] Queue appearance save for {0}",agentid);
160// DEBUG OFF 201// DEBUG OFF
161 sp.Appearance.SetAppearance(textureEntry, visualParams);
162 if (sp.Appearance.AvatarHeight > 0)
163 sp.SetHeight(sp.Appearance.AvatarHeight);
164 202
165 m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance); 203 // 100 nanoseconds (ticks) we should wait
204 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 10000000);
205 lock (m_savequeue)
206 {
207 m_savequeue[agentid] = timestamp;
208 m_updateTimer.Start();
209 }
210 }
211
212 private void HandleAppearanceSend(UUID agentid)
213 {
214 ScenePresence sp = m_scene.GetScenePresence(agentid);
215 if (sp == null)
216 {
217 m_log.WarnFormat("[AVFACTORY] Agent {0} no longer in the scene",agentid);
218 return;
166 } 219 }
220
167// DEBUG ON 221// DEBUG ON
168 else 222 m_log.WarnFormat("[AVFACTORY] Handle appearance send for {0}\n{1}",agentid,sp.Appearance.ToString());
169 m_log.Warn("[AVFACTORY] Appearance did not change"); 223// DEBUG OFF
170// DEBUG OFF
171 224
225 // Send the appearance to everyone in the scene
172 sp.SendAppearanceToAllOtherAgents(); 226 sp.SendAppearanceToAllOtherAgents();
227
228 // Send the appearance back to the avatar
229 AvatarAppearance avp = sp.Appearance;
230 sp.ControllingClient.SendAvatarDataImmediate(sp);
231 sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes());
232
233/*
234// this needs to be fixed, the flag should be on scene presence not the region module
235 // Start the animations if necessary
173 if (!m_startAnimationSet) 236 if (!m_startAnimationSet)
174 { 237 {
175 sp.Animator.UpdateMovementAnimations(); 238 sp.Animator.UpdateMovementAnimations();
176 m_startAnimationSet = true; 239 m_startAnimationSet = true;
177 } 240 }
241*/
242 }
178 243
179 client.SendAvatarDataImmediate(sp); 244 private void HandleAppearanceSave(UUID agentid)
180 client.SendAppearance(sp.Appearance.Owner,sp.Appearance.VisualParams,sp.Appearance.Texture.GetBytes()); 245 {
246 ScenePresence sp = m_scene.GetScenePresence(agentid);
247 if (sp == null)
248 {
249 m_log.WarnFormat("[AVFACTORY] Agent {0} no longer in the scene",agentid);
250 return;
251 }
252
253 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
181 } 254 }
182 255
256 private void HandleAppearanceUpdateTimer(object sender, EventArgs ea)
257 {
258 long now = DateTime.Now.Ticks;
259
260 lock (m_sendqueue)
261 {
262 Dictionary<UUID,long> sends = new Dictionary<UUID,long>(m_sendqueue);
263 foreach (KeyValuePair<UUID,long> kvp in sends)
264 {
265 if (kvp.Value < now)
266 {
267 Util.FireAndForget(delegate(object o) { HandleAppearanceSend(kvp.Key); });
268 m_sendqueue.Remove(kvp.Key);
269 }
270 }
271 }
272
273 lock (m_savequeue)
274 {
275 Dictionary<UUID,long> saves = new Dictionary<UUID,long>(m_savequeue);
276 foreach (KeyValuePair<UUID,long> kvp in saves)
277 {
278 if (kvp.Value < now)
279 {
280 Util.FireAndForget(delegate(object o) { HandleAppearanceSave(kvp.Key); });
281 m_savequeue.Remove(kvp.Key);
282 }
283 }
284 }
285
286 if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
287 m_updateTimer.Stop();
288 }
289
290 #endregion
291
183 /// <summary> 292 /// <summary>
184 /// Tell the client for this scene presence what items it should be wearing now 293 /// Tell the client for this scene presence what items it should be wearing now
185 /// </summary> 294 /// </summary>