/// <summary> /// Update the given part with the new texture. /// </summary> /// <returns> /// The old texture UUID. /// </returns> public UUID UpdatePart(SceneObjectPart part, UUID textureID) { UUID oldID; lock (part) { // mostly keep the values from before Primitive.TextureEntry tmptex = part.Shape.Textures; // FIXME: Need to return the appropriate ID if only a single face is replaced. oldID = tmptex.DefaultTexture.TextureID; // not using parts number of faces because that fails on old meshs if (Face == ALL_SIDES) { oldID = tmptex.DefaultTexture.TextureID; tmptex.DefaultTexture.TextureID = textureID; for (int i = 0; i < tmptex.FaceTextures.Length; i++) { if (tmptex.FaceTextures[i] != null) { tmptex.FaceTextures[i].TextureID = textureID; } } } else { try { Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); oldID = texface.TextureID; texface.TextureID = textureID; tmptex.FaceTextures[Face] = texface; } catch (Exception) { tmptex.DefaultTexture.TextureID = textureID; } } part.UpdateTextureEntry(tmptex); } return(oldID); }
/// <summary> /// Update the given part with the new texture. /// </summary> /// <returns> /// The old texture UUID. /// </returns> public UUID UpdatePart(SceneObjectPart part, UUID textureID) { UUID oldID; lock (part) { // mostly keep the values from before Primitive.TextureEntry tmptex = part.Shape.Textures; // FIXME: Need to return the appropriate ID if only a single face is replaced. oldID = tmptex.DefaultTexture.TextureID; if (Face == ALL_SIDES) { oldID = tmptex.DefaultTexture.TextureID; tmptex.DefaultTexture.TextureID = textureID; } else { try { Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); texface.TextureID = textureID; tmptex.FaceTextures[Face] = texface; } catch (Exception) { tmptex.DefaultTexture.TextureID = textureID; } } // I'm pretty sure we always want to force this to true // I'm pretty sure noone whats to set fullbright true if it wasn't true before. // tmptex.DefaultTexture.Fullbright = true; part.UpdateTextureEntry(tmptex.GetBytes()); } return(oldID); }
/// <summary> /// Assign a single material value. Based on the values passed we'll either set (or clear) the materials for a SOP. /// </summary> /// <param name="sop">The SOP being affected.</param> /// <param name="face">The face to assign, or -1 if the default texture is being set.</param> /// <param name="id">The ID assigned to this material. Setting a Zero UUID clears it.</param> /// <param name="material">If not null, the material to set. Otherwise we are clearing.</param> private void AssignSingleMaterial(SceneObjectPart sop, int face, OSDMap matData) { /// Get a copy of the texture entry so we can make changes. var te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length); if (te == null) { m_log.Warn("[RenderMaterials]: null TextureEntry for localId: " + sop.LocalId.ToString()); return; } lock (m_knownMaterials) { UUID id = UUID.Zero; // Record what we currently have var currentMaterialIDs = getMaterialIDsFromTextureEntry(te); // If there is a material being set see if we've seen it before. // If not we'll add it to the region cache if (matData != null) { RenderMaterial material = RenderMaterial.FromOSD(matData); id = sop.Shape.RenderMaterials.AddMaterial(material); if (m_knownMaterials.ContainsKey(id)) { material = m_knownMaterials[id].material; var entry = m_knownMaterials[id]; if (entry.partIds.Contains(sop.LocalId) == false) { entry.partIds.Add(sop.LocalId); } } else { m_knownMaterials[id] = new RenderMaterialEntry(material, sop.LocalId); } m_log.DebugFormat("[RenderMaterials]: SOP {0}, Face {1}, Adding RenderMaterial {2}", sop.LocalId, face, material.ToString()); } // Set the Material ID in the sop texture entry. If there's a face defined // use that else use the Default entry. ID can either be a material ID // we set from the lookup above or Zero when we are clearing a material. if (face < 0) { te.DefaultTexture.MaterialID = id; } else { var faceEntry = te.CreateFace((uint)face); faceEntry.MaterialID = id; } // Get the updated list of Materials from the TextureEntry. We will // Use that to rebuild the RenderMaterials for the part. We'll also get a list // of entries that have been removed based on what we fetched initially so we // can clean that up in our cache. var newMaterialIDs = getMaterialIDsFromTextureEntry(te); // If there was an update and the material id has changed, clean up the old value. // Have to be careful here. It might still be in use in another slot. So we build // a list of keys and walk the texture entries subtracting keys in use. Whatever // is left are candidates to clean up. foreach (var entry in newMaterialIDs) { if (currentMaterialIDs.Contains(entry)) { currentMaterialIDs.Remove(entry); } if (sop.Shape.RenderMaterials.ContainsMaterial(entry) == false) { m_log.WarnFormat("[RenderMaterials]: SOP {0}, Face {1}, RenderMaterials {2} should be present but isn't!", sop.LocalId, face, entry.ToString()); } } // currentMaterialsIDs contains orphans if any. Remove them from the sop.Shape and the cache (if needed) foreach (var entry in currentMaterialIDs) { if (sop.Shape.RenderMaterials.ContainsMaterial(entry) == true) { m_log.DebugFormat("[RenderMaterials]: SOP {0}, Face {1}, Removing unused RenderMaterials {2} from shape.", sop.LocalId, face, entry.ToString()); sop.Shape.RenderMaterials.RemoveMaterial(entry); } else { m_log.WarnFormat("[RenderMaterials]: SOP {0}, Face {1}, ORPHANED RenderMaterials {2} should be present but isn't!", sop.LocalId, face, entry.ToString()); } if (m_knownMaterials.ContainsKey(entry)) { m_knownMaterials[entry].partIds.Remove(sop.LocalId); if (m_knownMaterials[entry].partIds.Count <= 0) { m_log.DebugFormat("[RenderMaterials]: Removing unused RenderMaterials {0} from region cache.", entry.ToString()); m_knownMaterials.Remove(entry); } } } } // Update the texture entry which will force an update to connected clients sop.UpdateTextureEntry(te.GetBytes()); }
/// <summary> /// Called once new texture data has been received for this updater. /// </summary> public void DataReceived(byte[] data, Scene scene) { SceneObjectPart part = scene.GetSceneObjectPart(PrimID); if (part == null || data == null || data.Length <= 1) { string msg = String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); return; } byte[] assetData = null; AssetBase oldAsset = null; if (BlendWithOldTexture) { Primitive.TextureEntryFace defaultFace = part.Shape.Textures.DefaultTexture; if (defaultFace != null) { oldAsset = scene.AssetService.Get(defaultFace.TextureID.ToString()); if (oldAsset != null) { assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha); } } } if (assetData == null) { assetData = new byte[data.Length]; Array.Copy(data, assetData, data.Length); } // Create a new asset for user AssetBase asset = new AssetBase( UUID.Random(), "DynamicImage" + Util.RandomClass.Next(1, 10000), (sbyte)AssetType.Texture, scene.RegionInfo.RegionID.ToString()); asset.Data = assetData; asset.Description = String.Format("URL image : {0}", Url); asset.Local = false; asset.Temporary = ((Disp & DISP_TEMP) != 0); scene.AssetService.Store(asset); IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface <IJ2KDecoder>(); if (cacheLayerDecode != null) { cacheLayerDecode.Decode(asset.FullID, asset.Data); cacheLayerDecode = null; } UUID oldID = UUID.Zero; lock (part) { // mostly keep the values from before Primitive.TextureEntry tmptex = part.Shape.Textures; // remove the old asset from the cache oldID = tmptex.DefaultTexture.TextureID; if (Face == ALL_SIDES) { tmptex.DefaultTexture.TextureID = asset.FullID; } else { try { Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); texface.TextureID = asset.FullID; tmptex.FaceTextures[Face] = texface; } catch (Exception) { tmptex.DefaultTexture.TextureID = asset.FullID; } } // I'm pretty sure we always want to force this to true // I'm pretty sure noone whats to set fullbright true if it wasn't true before. // tmptex.DefaultTexture.Fullbright = true; part.UpdateTextureEntry(tmptex.GetBytes()); } if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) { if (oldAsset == null) { oldAsset = scene.AssetService.Get(oldID.ToString()); } if (oldAsset != null) { if (oldAsset.Temporary == true) { scene.AssetService.Delete(oldID.ToString()); } } } }