diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | 125 |
1 files changed, 67 insertions, 58 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 0df4585..7d6d191 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | |||
@@ -115,8 +115,19 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
115 | 115 | ||
116 | #endregion | 116 | #endregion |
117 | 117 | ||
118 | /// <summary> | ||
119 | /// Check for the existence of the baked texture assets. Request a rebake | ||
120 | /// unless checkonly is true. | ||
121 | /// </summary> | ||
122 | /// <param name="client"></param> | ||
123 | /// <param name="checkonly"></param> | ||
118 | public bool ValidateBakedTextureCache(IClientAPI client) | 124 | public bool ValidateBakedTextureCache(IClientAPI client) |
119 | { | 125 | { |
126 | return ValidateBakedTextureCache(client, true); | ||
127 | } | ||
128 | |||
129 | private bool ValidateBakedTextureCache(IClientAPI client, bool checkonly) | ||
130 | { | ||
120 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); | 131 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); |
121 | if (sp == null) | 132 | if (sp == null) |
122 | { | 133 | { |
@@ -131,15 +142,33 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
131 | { | 142 | { |
132 | int idx = AvatarAppearance.BAKE_INDICES[i]; | 143 | int idx = AvatarAppearance.BAKE_INDICES[i]; |
133 | Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; | 144 | Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; |
134 | if (face == null || face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) | 145 | |
146 | // if there is no texture entry, skip it | ||
147 | if (face == null) | ||
135 | continue; | 148 | continue; |
136 | 149 | ||
150 | // if the texture is one of the "defaults" then skip it | ||
151 | // this should probably be more intelligent (skirt texture doesnt matter | ||
152 | // if the avatar isnt wearing a skirt) but if any of the main baked | ||
153 | // textures is default then the rest should be as well | ||
154 | if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) | ||
155 | continue; | ||
156 | |||
137 | defonly = false; // found a non-default texture reference | 157 | defonly = false; // found a non-default texture reference |
138 | 158 | ||
139 | if (! CheckBakedTextureAsset(client,face.TextureID,idx)) | 159 | if (! CheckBakedTextureAsset(client,face.TextureID,idx)) |
140 | return false; | 160 | { |
161 | // the asset didn't exist if we are only checking, then we found a bad | ||
162 | // one and we're done otherwise, ask for a rebake | ||
163 | if (checkonly) return false; | ||
164 | |||
165 | m_log.InfoFormat("[AVFACTORY] missing baked texture {0}, request rebake",face.TextureID); | ||
166 | client.SendRebakeAvatarTextures(face.TextureID); | ||
167 | } | ||
141 | } | 168 | } |
142 | 169 | ||
170 | m_log.InfoFormat("[AVFACTORY]: complete texture check for {0}",client.AgentId); | ||
171 | |||
143 | // If we only found default textures, then the appearance is not cached | 172 | // If we only found default textures, then the appearance is not cached |
144 | return (defonly ? false : true); | 173 | return (defonly ? false : true); |
145 | } | 174 | } |
@@ -158,61 +187,43 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
158 | return; | 187 | return; |
159 | } | 188 | } |
160 | 189 | ||
161 | // m_log.WarnFormat("[AVFACTORY]: Start SetAppearance for {0}",client.AgentId); | 190 | m_log.InfoFormat("[AVFACTORY]: start SetAppearance for {0}",client.AgentId); |
162 | 191 | ||
192 | // TODO: This is probably not necessary any longer, just assume the | ||
193 | // textureEntry set implies that the appearance transaction is complete | ||
163 | bool changed = false; | 194 | bool changed = false; |
164 | 195 | ||
165 | // Process the texture entry transactionally, this doesn't guarantee that Appearance is | 196 | // Process the texture entry transactionally, this doesn't guarantee that Appearance is |
166 | // going to be handled correctly but it does serialize the updates to the appearance | 197 | // going to be handled correctly but it does serialize the updates to the appearance |
167 | lock (m_setAppearanceLock) | 198 | lock (m_setAppearanceLock) |
168 | { | 199 | { |
169 | if (textureEntry != null) | ||
170 | { | ||
171 | changed = sp.Appearance.SetTextureEntries(textureEntry); | ||
172 | |||
173 | // m_log.WarnFormat("[AVFACTORY]: Prepare to check textures for {0}",client.AgentId); | ||
174 | |||
175 | for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) | ||
176 | { | ||
177 | int idx = AvatarAppearance.BAKE_INDICES[i]; | ||
178 | Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; | ||
179 | if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) | ||
180 | Util.FireAndForget(delegate(object o) { | ||
181 | if (! CheckBakedTextureAsset(client,face.TextureID,idx)) | ||
182 | client.SendRebakeAvatarTextures(face.TextureID); | ||
183 | }); | ||
184 | } | ||
185 | |||
186 | // m_log.WarnFormat("[AVFACTORY]: Complete texture check for {0}",client.AgentId); | ||
187 | } | ||
188 | |||
189 | // Process the visual params, this may change height as well | 200 | // Process the visual params, this may change height as well |
190 | if (visualParams != null) | 201 | if (visualParams != null) |
191 | { | 202 | { |
192 | if (sp.Appearance.SetVisualParams(visualParams)) | 203 | changed = sp.Appearance.SetVisualParams(visualParams); |
193 | { | 204 | if (sp.Appearance.AvatarHeight > 0) |
194 | changed = true; | 205 | sp.SetHeight(sp.Appearance.AvatarHeight); |
195 | if (sp.Appearance.AvatarHeight > 0) | ||
196 | sp.SetHeight(sp.Appearance.AvatarHeight); | ||
197 | } | ||
198 | } | 206 | } |
199 | 207 | ||
200 | // Send the appearance back to the avatar, not clear that this is needed | 208 | // Process the baked texture array |
201 | sp.ControllingClient.SendAvatarDataImmediate(sp); | 209 | if (textureEntry != null) |
202 | // AvatarAppearance avp = sp.Appearance; | 210 | { |
203 | // sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes()); | 211 | changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; |
212 | |||
213 | m_log.InfoFormat("[AVFACTORY]: received texture update for {0}",client.AgentId); | ||
214 | Util.FireAndForget(delegate(object o) { ValidateBakedTextureCache(client,false); }); | ||
204 | 215 | ||
205 | } | 216 | // This appears to be set only in the final stage of the appearance |
206 | 217 | // update transaction. In theory, we should be able to do an immediate | |
218 | // appearance send and save here. | ||
207 | 219 | ||
208 | // If something changed in the appearance then queue an appearance save | 220 | QueueAppearanceSave(client.AgentId); |
209 | if (changed) | 221 | QueueAppearanceSend(client.AgentId); |
210 | QueueAppearanceSave(client.AgentId); | 222 | } |
211 | 223 | ||
212 | // And always queue up an appearance update to send out | 224 | } |
213 | QueueAppearanceSend(client.AgentId); | ||
214 | 225 | ||
215 | // m_log.WarnFormat("[AVFACTORY]: Complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString()); | 226 | // m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString()); |
216 | } | 227 | } |
217 | 228 | ||
218 | /// <summary> | 229 | /// <summary> |
@@ -235,6 +246,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
235 | 246 | ||
236 | #region UpdateAppearanceTimer | 247 | #region UpdateAppearanceTimer |
237 | 248 | ||
249 | /// <summary> | ||
250 | /// Queue up a request to send appearance, makes it possible to | ||
251 | /// accumulate changes without sending out each one separately. | ||
252 | /// </summary> | ||
238 | public void QueueAppearanceSend(UUID agentid) | 253 | public void QueueAppearanceSend(UUID agentid) |
239 | { | 254 | { |
240 | // m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid); | 255 | // m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid); |
@@ -274,21 +289,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
274 | 289 | ||
275 | // Send the appearance to everyone in the scene | 290 | // Send the appearance to everyone in the scene |
276 | sp.SendAppearanceToAllOtherAgents(); | 291 | sp.SendAppearanceToAllOtherAgents(); |
277 | // sp.ControllingClient.SendAvatarDataImmediate(sp); | ||
278 | |||
279 | // Send the appearance back to the avatar | ||
280 | // AvatarAppearance avp = sp.Appearance; | ||
281 | // sp.ControllingClient.SendAppearance(avp.Owner, avp.VisualParams, avp.Texture.GetBytes()); | ||
282 | 292 | ||
283 | /* | 293 | // Send animations back to the avatar as well |
284 | // this needs to be fixed, the flag should be on scene presence not the region module | 294 | sp.Animator.SendAnimPack(); |
285 | // Start the animations if necessary | ||
286 | if (!m_startAnimationSet) | ||
287 | { | ||
288 | sp.Animator.UpdateMovementAnimations(); | ||
289 | m_startAnimationSet = true; | ||
290 | } | ||
291 | */ | ||
292 | } | 295 | } |
293 | 296 | ||
294 | private void HandleAppearanceSave(UUID agentid) | 297 | private void HandleAppearanceSave(UUID agentid) |
@@ -374,8 +377,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
374 | 377 | ||
375 | // m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing called for {0}", client.AgentId); | 378 | // m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing called for {0}", client.AgentId); |
376 | 379 | ||
377 | AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false); | 380 | // we need to clean out the existing textures |
381 | sp.Appearance.ResetAppearance(); | ||
378 | 382 | ||
383 | // operate on a copy of the appearance so we don't have to lock anything | ||
384 | AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false); | ||
385 | |||
379 | foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) | 386 | foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) |
380 | { | 387 | { |
381 | if (wear.Type < AvatarWearable.MAX_WEARABLES) | 388 | if (wear.Type < AvatarWearable.MAX_WEARABLES) |
@@ -388,9 +395,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
388 | SetAppearanceAssets(sp.UUID, ref avatAppearance); | 395 | SetAppearanceAssets(sp.UUID, ref avatAppearance); |
389 | 396 | ||
390 | // could get fancier with the locks here, but in the spirit of "last write wins" | 397 | // could get fancier with the locks here, but in the spirit of "last write wins" |
391 | // this should work correctly | 398 | // this should work correctly, also, we don't need to send the appearance here |
399 | // since the "iswearing" will trigger a new set of visual param and baked texture changes | ||
400 | // when those complete, the new appearance will be sent | ||
392 | sp.Appearance = avatAppearance; | 401 | sp.Appearance = avatAppearance; |
393 | m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance); | 402 | QueueAppearanceSave(client.AgentId); |
394 | } | 403 | } |
395 | 404 | ||
396 | private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) | 405 | private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) |