several changes to materials, add llSet*PrimtiveParams*() support for them. They may be very broken now :(

httptests
UbitUmarov 2018-04-01 01:50:07 +01:00
parent f5365cb06d
commit ee6034f751
4 changed files with 992 additions and 335 deletions

View File

@ -26,10 +26,12 @@
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Cryptography; // for computing md5 hash
using OpenSim.Framework;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
namespace OpenSim.Region.Framework.Scenes
{
@ -93,38 +95,74 @@ namespace OpenSim.Region.Framework.Scenes
}
}
[StructLayout(LayoutKind.Sequential)]
public class FaceMaterial
{
public UUID ID;
public UUID NormalMapID = UUID.Zero;
public float NormalOffsetX = 0.0f;
public float NormalOffsetY = 0.0f;
public float NormalRepeatX = 1.0f;
public float NormalRepeatY = 1.0f;
public float NormalRotation = 0.0f;
// ll material data
public byte DiffuseAlphaMode = 1;
public byte AlphaMaskCutoff = 0;
public byte SpecularLightExponent = 51;
public byte EnvironmentIntensity = 0;
// need to have 4 bytes here
public float NormalOffsetX = 0.0f;
public float NormalOffsetY = 0.0f;
public float NormalRepeatX = 1.0f;
public float NormalRepeatY = 1.0f;
public float NormalRotation = 0.0f;
public UUID SpecularMapID = UUID.Zero;
public float SpecularOffsetX = 0.0f;
public float SpecularOffsetY = 0.0f;
public float SpecularRepeatX = 1.0f;
public float SpecularRepeatY = 1.0f;
public float SpecularRotation = 0.0f;
public float SpecularOffsetX = 0.0f;
public float SpecularOffsetY = 0.0f;
public float SpecularRepeatX = 1.0f;
public float SpecularRepeatY = 1.0f;
public float SpecularRotation = 0.0f;
public Color4 SpecularLightColor = new Color4(255,255,255,255);
public Byte SpecularLightExponent = 51;
public Byte EnvironmentIntensity = 0;
public Byte DiffuseAlphaMode = 1;
public Byte AlphaMaskCutoff = 0;
public byte SpecularLightColorR = 255;
public byte SpecularLightColorG = 255;
public byte SpecularLightColorB = 255;
public byte SpecularLightColorA = 255;
// data size 12 ints so far
public UUID NormalMapID = UUID.Zero;
public UUID SpecularMapID = UUID.Zero;
// other data
public UUID ID;
private int inthash;
private bool validinthash;
public FaceMaterial()
{ }
public FaceMaterial(UUID pID, OSDMap mat)
public FaceMaterial(FaceMaterial other)
{
if(other == null)
return;
DiffuseAlphaMode = other.DiffuseAlphaMode;
AlphaMaskCutoff = other.AlphaMaskCutoff;
SpecularLightExponent = other.SpecularLightExponent;
EnvironmentIntensity = other.EnvironmentIntensity;
NormalOffsetX = other.NormalOffsetX;
NormalOffsetY = other.NormalOffsetY;
NormalRepeatX = other.NormalRepeatX;
NormalRepeatY = other.NormalRepeatY;
NormalRotation = other.NormalRotation;
SpecularOffsetX = other.SpecularOffsetX;
SpecularOffsetY = other.SpecularOffsetY;
SpecularRepeatX = other.SpecularRepeatX;
SpecularRepeatY = other.SpecularRepeatY;
SpecularRotation = other.SpecularRotation;
SpecularLightColorR = other.SpecularLightColorR;
SpecularLightColorG = other.SpecularLightColorG;
SpecularLightColorB = other.SpecularLightColorB;
NormalMapID = other.NormalMapID;
SpecularMapID = other.SpecularMapID;
}
public FaceMaterial(OSDMap mat)
{
ID = pID;
if(mat == null)
return;
float scale = 0.0001f;
const float scale = 0.0001f;
NormalMapID = mat["NormMap"].AsUUID();
NormalOffsetX = scale * (float)mat["NormOffsetX"].AsReal();
NormalOffsetY = scale * (float)mat["NormOffsetY"].AsReal();
@ -139,13 +177,87 @@ namespace OpenSim.Region.Framework.Scenes
SpecularRepeatY = scale * (float)mat["SpecRepeatY"].AsReal();
SpecularRotation = scale * (float)mat["SpecRotation"].AsReal();
SpecularLightColor = mat["SpecColor"].AsColor4();
Color4 SpecularLightColortmp = mat["SpecColor"].AsColor4(); // we can read as color4
SpecularLightColorR = (byte)(SpecularLightColortmp.R);
SpecularLightColorG = (byte)(SpecularLightColortmp.G);
SpecularLightColorB = (byte)(SpecularLightColortmp.B);
SpecularLightExponent = (Byte)mat["SpecExp"].AsUInteger();
EnvironmentIntensity = (Byte)mat["EnvIntensity"].AsUInteger();
DiffuseAlphaMode = (Byte)mat["DiffuseAlphaMode"].AsUInteger();
AlphaMaskCutoff = (Byte)mat["AlphaMaskCutoff"].AsUInteger();
}
public void genID()
{
string lslx = toLLSDxml();
Byte[] data = System.Text.Encoding.ASCII.GetBytes(lslx);
using (var md5 = MD5.Create())
ID = new UUID(md5.ComputeHash(data), 0);
}
public unsafe override int GetHashCode()
{
if(!validinthash)
{
unchecked
{
// if you don't like this, don't read...
int* ptr;
fixed(byte* ptrbase = &DiffuseAlphaMode)
{
ptr = (int*)ptrbase;
inthash = *ptr;
for(int i = 0; i < 11; i++)
inthash ^= *ptr++;
}
fixed(Guid* ptrbase = &NormalMapID.Guid)
{
ptr = (int*)ptrbase;
for(int i = 0; i < 16; i++)
inthash ^= ptr[i];
}
fixed(Guid* ptrbase = &SpecularMapID.Guid)
{
ptr = (int*)ptrbase;
for(int i = 0; i < 16; i++)
inthash ^= ptr[i];
}
}
validinthash = true;
}
return inthash;
}
public override bool Equals(Object o)
{
if(o == null || !(o is FaceMaterial))
return false;
FaceMaterial other = (FaceMaterial)o;
return (
DiffuseAlphaMode == other.DiffuseAlphaMode
&& AlphaMaskCutoff == other.AlphaMaskCutoff
&& SpecularLightExponent == other.SpecularLightExponent
&& EnvironmentIntensity == other.EnvironmentIntensity
&& NormalMapID == other.NormalMapID
&& NormalOffsetX == other.NormalOffsetX
&& NormalOffsetY == other.NormalOffsetY
&& NormalRepeatX == other.NormalRepeatX
&& NormalRepeatY == other.NormalRepeatY
&& NormalRotation == other.NormalRotation
&& SpecularMapID == other.SpecularMapID
&& SpecularOffsetX == other.SpecularOffsetX
&& SpecularOffsetY == other.SpecularOffsetY
&& SpecularRepeatX == other.SpecularRepeatX
&& SpecularRepeatY == other.SpecularRepeatY
&& SpecularRotation == other.SpecularRotation
&& SpecularLightColorR == other.SpecularLightColorR
&& SpecularLightColorG == other.SpecularLightColorG
&& SpecularLightColorB == other.SpecularLightColorB
);
}
public OSDMap toOSD()
{
OSDMap mat = new OSDMap();
@ -165,7 +277,12 @@ namespace OpenSim.Region.Framework.Scenes
mat["SpecRepeatY"] = (int) (scale * SpecularRepeatY);
mat["SpecRotation"] = (int) (scale * SpecularRotation);
mat["SpecColor"] = SpecularLightColor;
OSDArray carray = new OSDArray(4);
carray.Add(SpecularLightColorR);
carray.Add(SpecularLightColorG);
carray.Add(SpecularLightColorB);
carray.Add(255); // solid color
mat["SpecColor"] = carray;
mat["SpecExp"] = SpecularLightExponent;
mat["EnvIntensity"] = EnvironmentIntensity;
mat["DiffuseAlphaMode"] = DiffuseAlphaMode;
@ -173,5 +290,53 @@ namespace OpenSim.Region.Framework.Scenes
return mat;
}
public string toLLSDxml(StringBuilder sb = null)
{
const float scale = 10000f;
bool fullLLSD = false;
if(sb == null)
{
sb = LLSDxmlEncode.Start(1024,false);
fullLLSD = true;
}
LLSDxmlEncode.AddMap(sb);
LLSDxmlEncode.AddElem("NormMap", NormalMapID, sb);
LLSDxmlEncode.AddElem("NormOffsetX", (int) (scale * NormalOffsetX + 0.5f), sb);
LLSDxmlEncode.AddElem("NormOffsetY", (int) (scale * NormalOffsetY + 0.5f), sb);
LLSDxmlEncode.AddElem("NormRepeatX", (int) (scale * NormalRepeatX + 0.5f), sb);
LLSDxmlEncode.AddElem("NormRepeatY", (int) (scale * NormalRepeatY + 0.5f), sb);
LLSDxmlEncode.AddElem("NormRotation", (int) (scale * NormalRotation + 0.5f), sb);
LLSDxmlEncode.AddElem("SpecMap", SpecularMapID, sb);
LLSDxmlEncode.AddElem("SpecOffsetX", (int) (scale * SpecularOffsetX + 0.5f), sb);
LLSDxmlEncode.AddElem("SpecOffsetY", (int) (scale * SpecularOffsetY + 0.5f), sb);
LLSDxmlEncode.AddElem("SpecRepeatX", (int) (scale * SpecularRepeatX + 0.5f), sb);
LLSDxmlEncode.AddElem("SpecRepeatY", (int) (scale * SpecularRepeatY + 0.5f), sb);
LLSDxmlEncode.AddElem("SpecRotation", (int) (scale * SpecularRotation + 0.5f), sb);
LLSDxmlEncode.AddArray("SpecColor", sb);
LLSDxmlEncode.AddElem(SpecularLightColorR, sb);
LLSDxmlEncode.AddElem(SpecularLightColorG, sb);
LLSDxmlEncode.AddElem(SpecularLightColorB, sb);
LLSDxmlEncode.AddElem(255, sb);
LLSDxmlEncode.AddEndArray(sb);
LLSDxmlEncode.AddElem("SpecExp", SpecularLightExponent, sb);
LLSDxmlEncode.AddElem("EnvIntensity", EnvironmentIntensity, sb);
LLSDxmlEncode.AddElem("DiffuseAlphaMode", DiffuseAlphaMode, sb);
LLSDxmlEncode.AddElem("AlphaMaskCutoff", AlphaMaskCutoff, sb);
LLSDxmlEncode.AddEndMap(sb);
if(fullLLSD)
{
return LLSDxmlEncode.End(sb);
}
else
return String.Empty; // ignored if appending
}
}
}

View File

@ -46,16 +46,10 @@ using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
using Ionic.Zlib;
// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
// the available DLLs
//[assembly: Addin("MaterialsModule", "1.0")]
//[assembly: AddinDependency("OpenSim", "0.8.1")]
namespace OpenSim.Region.OptionalModules.Materials
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsModule")]
public class MaterialsModule : INonSharedRegionModule
public class MaterialsModule : INonSharedRegionModule, IMaterialsModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -67,12 +61,12 @@ namespace OpenSim.Region.OptionalModules.Materials
private Scene m_scene = null;
private bool m_enabled = false;
private int m_maxMaterialsPerTransaction = 50;
private object materialslock = new object();
public Dictionary<UUID, OSDMap> m_Materials = new Dictionary<UUID, OSDMap>();
public Dictionary<UUID, FaceMaterial> m_Materials = new Dictionary<UUID, FaceMaterial>();
public Dictionary<UUID, int> m_MaterialsRefCount = new Dictionary<UUID, int>();
private Dictionary<ulong, AssetBase> m_changes = new Dictionary<ulong, AssetBase>();
private Dictionary<ulong, double> m_changesTime = new Dictionary<ulong, double>();
private Dictionary<FaceMaterial, double> m_changed = new Dictionary<FaceMaterial, double>();
public void Initialise(IConfigSource source)
{
@ -101,54 +95,72 @@ namespace OpenSim.Region.OptionalModules.Materials
return;
m_scene = scene;
m_scene.RegisterModuleInterface<IMaterialsModule>(this);
m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
m_scene.EventManager.OnObjectBeingRemovedFromScene += EventManager_OnObjectDeleteFromScene;
m_scene.EventManager.OnBackup += EventManager_OnBackup;
}
public void RemoveRegion(Scene scene)
{
if (!m_enabled)
return;
m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
m_scene.EventManager.OnObjectBeingRemovedFromScene -= EventManager_OnObjectDeleteFromScene;
m_scene.EventManager.OnBackup -= EventManager_OnBackup;
m_scene.UnregisterModuleInterface<IMaterialsModule>(this);
}
public void RegionLoaded(Scene scene)
{
if (!m_enabled) return;
m_cache = scene.RequestModuleInterface<IAssetCache>();
ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
if (featuresModule != null)
featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
}
private void EventManager_OnBackup(ISimulationDataService datastore, bool forcedBackup)
{
List<AssetBase> toStore;
List<ulong> hashlist;
List<FaceMaterial> toStore;
lock (m_Materials)
lock (materialslock)
{
if(m_changes.Count == 0)
if(m_changed.Count == 0)
return;
if(forcedBackup)
{
toStore = new List<AssetBase>(m_changes.Values);
m_changes.Clear();
m_changesTime.Clear();
toStore = new List<FaceMaterial>(m_changed.Keys);
m_changed.Clear();
}
else
{
toStore = new List<AssetBase>();
hashlist = new List<ulong>();
double storetime = Util.GetTimeStampMS() - 60000;
foreach(KeyValuePair<ulong,double> kvp in m_changesTime)
toStore = new List<FaceMaterial>();
double storetime = Util.GetTimeStamp() - 60.0;
foreach(KeyValuePair<FaceMaterial, double> kvp in m_changed)
{
if(kvp.Value < storetime)
{
toStore.Add(m_changes[kvp.Key]);
hashlist.Add(kvp.Key);
toStore.Add(kvp.Key);
}
}
foreach(ulong u in hashlist)
foreach(FaceMaterial fm in toStore)
{
m_changesTime.Remove(u);
m_changes.Remove(u);
m_changed.Remove(fm);
}
}
if(toStore.Count > 0)
Util.FireAndForget(delegate
{
foreach(AssetBase a in toStore)
foreach(FaceMaterial fm in toStore)
{
a.Local = false;
AssetBase a = MakeAsset(fm, false);
m_scene.AssetService.Store(a);
}
});
@ -162,6 +174,13 @@ namespace OpenSim.Region.OptionalModules.Materials
GetStoredMaterialsInPart(part);
}
private void EventManager_OnObjectDeleteFromScene(SceneObjectGroup obj)
{
foreach (var part in obj.Parts)
if (part != null)
RemoveMaterialsInPart(part);
}
private void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
{
string capsBase = "/CAPS/" + caps.CapsObjectPath;
@ -193,26 +212,6 @@ namespace OpenSim.Region.OptionalModules.Materials
MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler);
}
public void RemoveRegion(Scene scene)
{
if (!m_enabled)
return;
m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
m_scene.EventManager.OnBackup -= EventManager_OnBackup;
}
public void RegionLoaded(Scene scene)
{
if (!m_enabled) return;
m_cache = scene.RequestModuleInterface<IAssetCache>();
ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
if (featuresModule != null)
featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
}
private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
{
features["MaxMaterialsPerTransaction"] = m_maxMaterialsPerTransaction;
@ -222,14 +221,16 @@ namespace OpenSim.Region.OptionalModules.Materials
/// Finds any legacy materials stored in DynAttrs that may exist for this part and add them to 'm_regionMaterials'.
/// </summary>
/// <param name="part"></param>
private void GetLegacyStoredMaterialsInPart(SceneObjectPart part)
private bool GetLegacyStoredMaterialsInPart(SceneObjectPart part)
{
if (part.DynAttrs == null)
return;
return false;
OSD OSMaterials = null;
OSDArray matsArr = null;
bool partchanged = false;
lock (part.DynAttrs)
{
if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
@ -237,19 +238,21 @@ namespace OpenSim.Region.OptionalModules.Materials
OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
if (materialsStore == null)
return;
return false;
materialsStore.TryGetValue("Materials", out OSMaterials);
part.DynAttrs.RemoveStore("OpenSim", "Materials");
partchanged = true;
}
if (OSMaterials != null && OSMaterials is OSDArray)
matsArr = OSMaterials as OSDArray;
else
return;
return partchanged;
}
if (matsArr == null)
return;
return partchanged;
foreach (OSD elemOsd in matsArr)
{
@ -260,16 +263,24 @@ namespace OpenSim.Region.OptionalModules.Materials
{
try
{
lock (m_Materials)
lock (materialslock)
{
UUID id = matMap["ID"].AsUUID();
if(m_Materials.ContainsKey(id))
m_MaterialsRefCount[id]++;
else
{
m_Materials[id] = (OSDMap)matMap["Material"];
m_MaterialsRefCount[id] = 1;
}
continue;
OSDMap theMatMap = (OSDMap)matMap["Material"];
FaceMaterial fmat = new FaceMaterial(theMatMap);
if(fmat == null ||
( fmat.DiffuseAlphaMode == 1
&& fmat.NormalMapID == UUID.Zero
&& fmat.SpecularMapID == UUID.Zero))
continue;
fmat.ID = id;
m_Materials[id] = fmat;
m_MaterialsRefCount[id] = 0;
}
}
catch (Exception e)
@ -279,6 +290,7 @@ namespace OpenSim.Region.OptionalModules.Materials
}
}
}
return partchanged;
}
/// <summary>
@ -289,14 +301,16 @@ namespace OpenSim.Region.OptionalModules.Materials
if (part.Shape == null)
return;
bool partchanged = false;
bool facechanged = false;
var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
if (te == null)
return;
GetLegacyStoredMaterialsInPart(part);
partchanged = GetLegacyStoredMaterialsInPart(part);
if (te.DefaultTexture != null)
GetStoredMaterialInFace(part, te.DefaultTexture);
facechanged = GetStoredMaterialInFace(part, te.DefaultTexture);
else
m_log.WarnFormat(
"[Materials]: Default texture for part {0} (part of object {1}) in {2} unexpectedly null. Ignoring.",
@ -305,36 +319,47 @@ namespace OpenSim.Region.OptionalModules.Materials
foreach (Primitive.TextureEntryFace face in te.FaceTextures)
{
if (face != null)
GetStoredMaterialInFace(part, face);
facechanged |= GetStoredMaterialInFace(part, face);
}
if(facechanged)
part.Shape.TextureEntry = te.GetBytes();
if(facechanged || partchanged)
{
if (part.ParentGroup != null && !part.ParentGroup.IsDeleted)
part.ParentGroup.HasGroupChanged = true;
}
}
/// <summary>
/// Find the materials used in one Face, and add them to 'm_regionMaterials'.
/// </summary>
private void GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face)
private bool GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face)
{
UUID id = face.MaterialID;
if (id == UUID.Zero)
return;
return false;
lock (m_Materials)
OSDMap mat;
lock (materialslock)
{
if (m_Materials.ContainsKey(id))
if(m_Materials.ContainsKey(id))
{
m_MaterialsRefCount[id]++;
return;
return false;
}
AssetBase matAsset = m_scene.AssetService.Get(id.ToString());
if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 )
{
//m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id);
return;
// grid may just be down...
return false;
}
byte[] data = matAsset.Data;
OSDMap mat;
string txt = System.Text.Encoding.ASCII.GetString(data);
try
{
mat = (OSDMap)OSDParser.DeserializeLLSDXml(data);
@ -342,11 +367,76 @@ namespace OpenSim.Region.OptionalModules.Materials
catch (Exception e)
{
m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", id, e.Message);
return;
return false;
}
m_Materials[id] = mat;
m_MaterialsRefCount[id] = 1;
FaceMaterial fmat = new FaceMaterial(mat);
if(fmat == null ||
(fmat.DiffuseAlphaMode == 1
&& fmat.NormalMapID == UUID.Zero
&& fmat.SpecularMapID == UUID.Zero))
{
face.MaterialID = UUID.Zero;
return true;
}
fmat.ID = id;
if (m_Materials.ContainsKey(id))
{
m_MaterialsRefCount[id]++;
}
else
{
m_Materials[id] = fmat;
m_MaterialsRefCount[id] = 1;
}
return false;
}
}
private void RemoveMaterialsInPart(SceneObjectPart part)
{
if (part.Shape == null)
return;
var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
if (te == null)
return;
if (te.DefaultTexture != null)
RemoveMaterialInFace(te.DefaultTexture);
foreach (Primitive.TextureEntryFace face in te.FaceTextures)
{
if(face != null)
RemoveMaterialInFace(face);
}
}
private void RemoveMaterialInFace(Primitive.TextureEntryFace face)
{
UUID id = face.MaterialID;
if (id == UUID.Zero)
return;
lock (materialslock)
{
if(!m_Materials.ContainsKey(id))
return;
else
{
m_MaterialsRefCount[id]--;
if(m_MaterialsRefCount[id] <= 0)
{
FaceMaterial oldFaceMat = m_Materials[id];
m_changed.Remove(oldFaceMat);
m_Materials.Remove(id);
m_MaterialsRefCount.Remove(id);
m_cache.Expire(id.ToString());
}
}
}
}
@ -375,13 +465,13 @@ namespace OpenSim.Region.OptionalModules.Materials
{
UUID id = new UUID(elem.AsBinary(), 0);
lock (m_Materials)
lock (materialslock)
{
if (m_Materials.ContainsKey(id))
{
OSDMap matMap = new OSDMap();
matMap["ID"] = OSD.FromBinary(id.GetBytes());
matMap["Material"] = m_Materials[id];
matMap["Material"] = m_Materials[id].toOSD();
respArr.Add(matMap);
}
else
@ -455,10 +545,12 @@ namespace OpenSim.Region.OptionalModules.Materials
foreach (OSDMap matsMap in matsArr)
{
uint primLocalID = 0;
try {
try
{
primLocalID = matsMap["ID"].AsUInteger();
}
catch (Exception e) {
catch (Exception e)
{
m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message);
continue;
}
@ -494,7 +586,22 @@ namespace OpenSim.Region.OptionalModules.Materials
continue;
}
int face = -1;
UUID oldid = UUID.Zero;
Primitive.TextureEntryFace faceEntry = null;
if (matsMap.ContainsKey("Face"))
{
face = matsMap["Face"].AsInteger();
faceEntry = te.CreateFace((uint)face);
}
else
faceEntry = te.DefaultTexture;
if (faceEntry == null)
continue;
UUID id;
FaceMaterial newFaceMat = null;
if (mat == null)
{
// This happens then the user removes a material from a prim
@ -502,60 +609,48 @@ namespace OpenSim.Region.OptionalModules.Materials
}
else
{
id = getNewID(mat);
}
int face = -1;
UUID oldid = UUID.Zero;
if (matsMap.ContainsKey("Face"))
{
face = matsMap["Face"].AsInteger();
Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
oldid = faceEntry.MaterialID;
faceEntry.MaterialID = id;
}
else
{
if (te.DefaultTexture == null)
m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
newFaceMat = new FaceMaterial(mat);
if(newFaceMat.DiffuseAlphaMode == 1
&& newFaceMat.NormalMapID == UUID.Zero
&& newFaceMat.SpecularMapID == UUID.Zero
)
id = UUID.Zero;
else
{
oldid = te.DefaultTexture.MaterialID;
te.DefaultTexture.MaterialID = id;
newFaceMat.genID();
id = newFaceMat.ID;
}
}
//m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
oldid = faceEntry.MaterialID;
// We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
sop.Shape.TextureEntry = te.GetBytes();
if(oldid == id)
continue;
lock(m_Materials)
if (faceEntry != null)
{
if(oldid != UUID.Zero && m_MaterialsRefCount.ContainsKey(oldid))
{
m_MaterialsRefCount[oldid]--;
if(m_MaterialsRefCount[oldid] <= 0)
{
m_Materials.Remove(oldid);
m_MaterialsRefCount.Remove(oldid);
m_cache.Expire(oldid.ToString());
}
}
faceEntry.MaterialID = id;
//m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
// We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
sop.Shape.TextureEntry = te.GetBytes();
}
if(oldid != UUID.Zero)
RemoveMaterial(oldid);
lock(materialslock)
{
if(id != UUID.Zero)
{
AssetBase asset = CacheMaterialAsAsset(id, agentID, mat, sop);
if(asset != null)
if (m_Materials.ContainsKey(id))
m_MaterialsRefCount[id]++;
else
{
ulong materialHash = (ulong)primLocalID << 32;
if(face < 0)
materialHash += 0xffffffff;
else
materialHash +=(ulong)face;
m_changes[materialHash] = asset;
m_changesTime[materialHash] = Util.GetTimeStampMS();
m_Materials[id] = newFaceMat;
m_MaterialsRefCount[id] = 1;
m_changed[newFaceMat] = Util.GetTimeStamp();
}
}
}
@ -598,119 +693,39 @@ namespace OpenSim.Region.OptionalModules.Materials
return response;
}
private UUID getNewID(OSDMap mat)
{
// ugly and done twice but keep compatibility for now
Byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
using (var md5 = MD5.Create())
return new UUID(md5.ComputeHash(data), 0);
}
private AssetBase CacheMaterialAsAsset(UUID id, UUID agentID, OSDMap mat, SceneObjectPart sop)
private AssetBase MakeAsset(FaceMaterial fm, bool local)
{
// this are not true assets, should had never been...
AssetBase asset = null;
lock (m_Materials)
{
if (!m_Materials.ContainsKey(id))
{
m_Materials[id] = mat;
m_MaterialsRefCount[id] = 1;
string txt = fm.toLLSDxml();
byte[] data = System.Text.Encoding.ASCII.GetBytes(txt);
byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
// This asset might exist already, but it's ok to try to store it again
string name = "Material " + ChooseMaterialName(mat, sop);
name = name.Substring(0, Math.Min(64, name.Length)).Trim();
asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString());
asset.Data = data;
asset.Local = true;
m_cache.Cache(asset);
}
else
m_MaterialsRefCount[id]++;
}
asset = new AssetBase(fm.ID, "llmaterial", (sbyte)OpenSimAssetType.Material, "00000000-0000-0000-0000-000000000000");
asset.Data = data;
asset.Local = local;
return asset;
}
private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop)
{
UUID id;
// Material UUID = hash of the material's data.
// This makes materials deduplicate across the entire grid (but isn't otherwise required).
byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
using (var md5 = MD5.Create())
id = new UUID(md5.ComputeHash(data), 0);
lock (m_Materials)
{
if (!m_Materials.ContainsKey(id))
{
m_Materials[id] = mat;
m_MaterialsRefCount[id] = 1;
// This asset might exist already, but it's ok to try to store it again
string name = "Material " + ChooseMaterialName(mat, sop);
name = name.Substring(0, Math.Min(64, name.Length)).Trim();
AssetBase asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString());
asset.Data = data;
m_scene.AssetService.Store(asset);
}
else
m_MaterialsRefCount[id]++;
}
return id;
}
/// <summary>
/// Use heuristics to choose a good name for the material.
/// </summary>
private string ChooseMaterialName(OSDMap mat, SceneObjectPart sop)
{
UUID normMap = mat["NormMap"].AsUUID();
if (normMap != UUID.Zero)
{
AssetBase asset = m_scene.AssetService.GetCached(normMap.ToString());
if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
return asset.Name;
}
UUID specMap = mat["SpecMap"].AsUUID();
if (specMap != UUID.Zero)
{
AssetBase asset = m_scene.AssetService.GetCached(specMap.ToString());
if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
return asset.Name;
}
if (sop.Name != "Primitive")
return sop.Name;
if ((sop.ParentGroup != null) && (sop.ParentGroup.Name != "Primitive"))
return sop.ParentGroup.Name;
return "";
}
public string RenderMaterialsGetCap(string request)
{
OSDMap resp = new OSDMap();
int matsCount = 0;
OSDArray allOsd = new OSDArray();
/*
// this violates all idea of caching and geting things only if needed, so disabled
int matsCount = 0;
lock (m_Materials)
{
foreach (KeyValuePair<UUID, OSDMap> kvp in m_Materials)
foreach (KeyValuePair<UUID, FaceMaterial> kvp in m_Materials)
{
OSDMap matMap = new OSDMap();
matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes());
matMap["Material"] = kvp.Value;
matMap["Material"] = kvp.Value.toOSD();
allOsd.Add(matMap);
matsCount++;
}
}
*/
resp["Zipped"] = ZCompressOSD(allOsd, false);
return OSDParser.SerializeLLSDXmlString(resp);
@ -728,18 +743,6 @@ namespace OpenSim.Region.OptionalModules.Materials
}
}
/// <summary>
/// computes a UUID by hashing a OSD object
/// </summary>
/// <param name="osd"></param>
/// <returns></returns>
private static UUID HashOsd(OSD osd)
{
byte[] data = OSDParser.SerializeLLSDBinary(osd, false);
using (var md5 = MD5.Create())
return new UUID(md5.ComputeHash(data), 0);
}
public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
{
OSD osd = null;
@ -761,7 +764,6 @@ namespace OpenSim.Region.OptionalModules.Materials
return osd;
}
public static OSD ZDecompressBytesToOsd(byte[] input)
{
OSD osd = null;
@ -779,5 +781,67 @@ namespace OpenSim.Region.OptionalModules.Materials
return osd;
}
public FaceMaterial GetMaterial(UUID ID)
{
FaceMaterial fm = null;
if(m_Materials.TryGetValue(ID, out fm))
return fm;
return null;
}
public FaceMaterial GetMaterialCopy(UUID ID)
{
FaceMaterial fm = null;
if(m_Materials.TryGetValue(ID, out fm))
return new FaceMaterial(fm);
return null;
}
public UUID AddNewMaterial(FaceMaterial fm)
{
if(fm.DiffuseAlphaMode == 1 && fm.NormalMapID == UUID.Zero && fm.SpecularMapID == UUID.Zero)
{
fm.ID = UUID.Zero;
return UUID.Zero;
}
fm.genID();
UUID id = fm.ID;
lock(materialslock)
{
if(m_Materials.ContainsKey(id))
m_MaterialsRefCount[id]++;
else
{
m_Materials[id] = fm;
m_MaterialsRefCount[id] = 1;
m_changed[fm] = Util.GetTimeStamp();
}
}
return id;
}
public void RemoveMaterial(UUID id)
{
if(id == UUID.Zero)
return;
lock(materialslock)
{
if(m_Materials.ContainsKey(id))
{
m_MaterialsRefCount[id]--;
if(m_MaterialsRefCount[id] <= 0)
{
FaceMaterial fm = m_Materials[id];
m_changed.Remove(fm);
m_Materials.Remove(id);
m_MaterialsRefCount.Remove(id);
m_cache.Expire(id.ToString());
}
}
}
}
}
}

View File

@ -124,6 +124,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected bool m_debuggerSafe = false;
protected IUrlModule m_UrlModule = null;
protected IMaterialsModule m_materialsModule = null;
protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>();
protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
protected int m_sleepMsOnSetTexture = 200;
@ -306,6 +308,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
m_materialsModule = m_ScriptEngine.World.RequestModuleInterface<IMaterialsModule>();
AsyncCommands = new AsyncCommandManager(m_ScriptEngine);
}
@ -2458,7 +2461,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return;
}
Primitive.TextureEntry tex = part.Shape.Textures;
int nsides = GetNumberOfSides(part);
@ -8910,6 +8912,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
SceneObjectGroup parentgrp = part.ParentGroup;
bool positionChanged = false;
bool materialChanged = false;
LSL_Vector currentPosition = GetPartLocalPos(part);
try
@ -10206,6 +10209,231 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break;
case ScriptBaseClass.PRIM_ALPHA_MODE:
if (remain < 3)
return new LSL_List();
try
{
face = rules.GetLSLIntegerItem(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ALPHA_MODE: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
int materialAlphaMode;
try
{
materialAlphaMode = rules.GetLSLIntegerItem(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ALPHA_MODE: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
if(materialAlphaMode < 0 || materialAlphaMode > 3)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ALPHA_MODE: arg #{1} - must be 0 to 3", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
int materialMaskCutoff;
try
{
materialMaskCutoff = rules.GetLSLIntegerItem(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ALPHA_MODE: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
if(materialMaskCutoff < 0 || materialMaskCutoff > 255)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ALPHA_MODE: arg #{1} - must be 0 to 255", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
materialChanged |= SetMaterialAlphaMode(part, face, materialAlphaMode, materialMaskCutoff);
break;
case ScriptBaseClass.PRIM_NORMAL:
if (remain < 5)
return new LSL_List();
try
{
face = rules.GetLSLIntegerItem(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NORMAL: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
string mapname = rules.Data[idx++].ToString();
UUID mapID = ScriptUtils.GetAssetIdFromItemName(m_host, mapname, (int)AssetType.Texture);
if (mapID == UUID.Zero)
{
if (!UUID.TryParse(mapname, out mapID))
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NORMAL: arg #{1} - must be a UUID or a texture name on object inventory", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
}
LSL_Vector mnrepeat;
try
{
mnrepeat = rules.GetVector3Item(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NORMAL: arg #{1} - must be vector", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
LSL_Vector mnoffset;
try
{
mnoffset = rules.GetVector3Item(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NORMAL: arg #{1} - must be vector", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
LSL_Float mnrot;
try
{
mnrot = rules.GetLSLFloatItem(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NORMAL: arg #{1} - must be float", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
float repeatX = (float)Util.Clamp(mnrepeat.x,-100.0, 100.0);
float repeatY = (float)Util.Clamp(mnrepeat.y,-100.0, 100.0);
float offsetX = (float)Util.Clamp(mnoffset.x, 0, 1.0);
float offsetY = (float)Util.Clamp(mnoffset.y, 0, 1.0);
materialChanged |= SetMaterialNormalMap(part, face, mapID, repeatX, repeatY, offsetX, offsetY, (float)mnrot);
break;
case ScriptBaseClass.PRIM_SPECULAR:
if (remain < 8)
return new LSL_List();
try
{
face = rules.GetLSLIntegerItem(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
string smapname = rules.Data[idx++].ToString();
UUID smapID = ScriptUtils.GetAssetIdFromItemName(m_host, smapname, (int)AssetType.Texture);
if (smapID == UUID.Zero)
{
if (!UUID.TryParse(smapname, out smapID))
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be a UUID or a texture name on object inventory", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
}
LSL_Vector msrepeat;
try
{
msrepeat = rules.GetVector3Item(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be vector", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
LSL_Vector msoffset;
try
{
msoffset = rules.GetVector3Item(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be vector", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
LSL_Float msrot;
try
{
msrot = rules.GetLSLFloatItem(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be float", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
LSL_Vector mscolor;
try
{
mscolor = rules.GetVector3Item(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be vector", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
LSL_Integer msgloss;
try
{
msgloss = rules.GetLSLIntegerItem(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
LSL_Integer msenv;
try
{
msenv = rules.GetLSLIntegerItem(idx++);
}
catch(InvalidCastException)
{
Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
return new LSL_List();
}
float srepeatX = (float)Util.Clamp(msrepeat.x, -100.0, 100.0);
float srepeatY = (float)Util.Clamp(msrepeat.y, -100.0, 100.0);
float soffsetX = (float)Util.Clamp(msoffset.x, -1.0, 1.0);
float soffsetY = (float)Util.Clamp(msoffset.y, -1.0, 1.0);
byte colorR = (byte)(255.0 * Util.Clamp(mscolor.x, 0, 1.0) + 0.5);
byte colorG = (byte)(255.0 * Util.Clamp(mscolor.y, 0, 1.0) + 0.5);
byte colorB = (byte)(255.0 * Util.Clamp(mscolor.z, 0, 1.0) + 0.5);
byte gloss = (byte)Util.Clamp((int)msgloss, 0, 255);
byte env = (byte)Util.Clamp((int)msenv, 0, 255);
materialChanged |= SetMaterialSpecMap(part, face, smapID, srepeatX, srepeatY, soffsetX, soffsetY,
(float)msrot, colorR, colorG, colorB, gloss, env);
break;
case ScriptBaseClass.PRIM_LINK_TARGET:
if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
return new LSL_List();
@ -10242,11 +10470,194 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
part.ScheduleTerseUpdate();
}
}
if(materialChanged)
{
if (part.ParentGroup != null && !part.ParentGroup.IsDeleted)
{
part.TriggerScriptChangedEvent(Changed.TEXTURE);
part.ScheduleFullUpdate();
part.ParentGroup.HasGroupChanged = true;
}
}
}
return new LSL_List();
}
protected bool SetMaterialAlphaMode(SceneObjectPart part, int face, int materialAlphaMode, int materialMaskCutoff)
{
if(m_materialsModule == null)
return false;
int nsides = part.GetNumberOfSides();
if(face == ScriptBaseClass.ALL_SIDES)
{
bool changed = false;
for(int i = 0; i < nsides; i++)
changed |= SetFaceMaterialAlphaMode(part, i, materialAlphaMode, materialMaskCutoff);
return changed;
}
if( face >= 0 && face < nsides)
return SetFaceMaterialAlphaMode(part, face, materialAlphaMode, materialMaskCutoff);
return false;
}
protected bool SetFaceMaterialAlphaMode(SceneObjectPart part, int face, int materialAlphaMode, int materialMaskCutoff)
{
Primitive.TextureEntry tex = part.Shape.Textures;
Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
if(texface == null)
return false;
FaceMaterial mat = null;
UUID oldid = texface.MaterialID;
if(oldid != UUID.Zero)
mat = m_materialsModule.GetMaterialCopy(oldid);
if(mat == null)
mat = new FaceMaterial();
mat.DiffuseAlphaMode = (byte)materialAlphaMode;
mat.AlphaMaskCutoff = (byte)materialMaskCutoff;
UUID id = m_materialsModule.AddNewMaterial(mat);
if(oldid == id)
return false;
texface.MaterialID = id;
part.Shape.TextureEntry = tex.GetBytes();
m_materialsModule.RemoveMaterial(oldid);
return true;
}
protected bool SetMaterialNormalMap(SceneObjectPart part, int face, UUID mapID, float repeatX, float repeatY,
float offsetX, float offsetY, float rot)
{
if(m_materialsModule == null)
return false;
int nsides = part.GetNumberOfSides();
if(face == ScriptBaseClass.ALL_SIDES)
{
bool changed = false;
for(int i = 0; i < nsides; i++)
changed |= SetFaceMaterialNormalMap(part, i, mapID, repeatX, repeatY, offsetX, offsetY, rot);
return changed;
}
if( face >= 0 && face < nsides)
return SetFaceMaterialNormalMap(part, face, mapID, repeatX, repeatY, offsetX, offsetY, rot);
return false;
}
protected bool SetFaceMaterialNormalMap(SceneObjectPart part, int face, UUID mapID, float repeatX, float repeatY,
float offsetX, float offsetY, float rot)
{
Primitive.TextureEntry tex = part.Shape.Textures;
Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
if(texface == null)
return false;
FaceMaterial mat = null;
UUID oldid = texface.MaterialID;
if(oldid != UUID.Zero)
mat = m_materialsModule.GetMaterialCopy(oldid);
if(mat == null)
mat = new FaceMaterial();
mat.NormalMapID = mapID;
mat.NormalOffsetX = offsetX;
mat.NormalOffsetY = offsetY;
mat.NormalRepeatX = repeatX;
mat.NormalRepeatY = repeatY;
mat.NormalRotation = rot;
UUID id = m_materialsModule.AddNewMaterial(mat);
if(oldid == id)
return false;
texface.MaterialID = id;
part.Shape.TextureEntry = tex.GetBytes();
m_materialsModule.RemoveMaterial(oldid);
return true;
}
protected bool SetMaterialSpecMap(SceneObjectPart part, int face, UUID mapID, float repeatX, float repeatY,
float offsetX, float offsetY, float rot,
byte colorR, byte colorG, byte colorB,
byte gloss, byte env)
{
if(m_materialsModule == null)
return false;
int nsides = part.GetNumberOfSides();
if(face == ScriptBaseClass.ALL_SIDES)
{
bool changed = false;
for(int i = 0; i < nsides; i++)
changed |= SetFaceMaterialSpecMap(part, i, mapID, repeatX, repeatY, offsetX, offsetY, rot,
colorR, colorG, colorB, gloss, env);
return changed;
}
if( face >= 0 && face < nsides)
return SetFaceMaterialSpecMap(part, face, mapID, repeatX, repeatY, offsetX, offsetY, rot,
colorR, colorG, colorB, gloss, env);
return false;
}
protected bool SetFaceMaterialSpecMap(SceneObjectPart part, int face, UUID mapID, float repeatX, float repeatY,
float offsetX, float offsetY, float rot,
byte colorR, byte colorG, byte colorB,
byte gloss, byte env)
{
Primitive.TextureEntry tex = part.Shape.Textures;
Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
if(texface == null)
return false;
FaceMaterial mat = null;
UUID oldid = texface.MaterialID;
if(oldid != UUID.Zero)
mat = m_materialsModule.GetMaterialCopy(oldid);
if(mat == null)
mat = new FaceMaterial();
mat.SpecularMapID = mapID;
mat.SpecularOffsetX = offsetX;
mat.SpecularOffsetY = offsetY;
mat.SpecularRepeatX = repeatX;
mat.SpecularRepeatY = repeatY;
mat.SpecularRotation = rot;
mat.SpecularLightColorR = colorR;
mat.SpecularLightColorG = colorG;
mat.SpecularLightColorB = colorB;
mat.SpecularLightExponent = gloss;
mat.EnvironmentIntensity = env;
UUID id = m_materialsModule.AddNewMaterial(mat);
if(oldid == id)
return false;
texface.MaterialID = id;
part.Shape.TextureEntry = tex.GetBytes();
m_materialsModule.RemoveMaterial(oldid);
return true;
}
protected LSL_List SetAgentParams(ScenePresence sp, LSL_List rules, string originFunc, ref uint rulesParsed)
{
int idx = 0;
@ -11363,107 +11774,83 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return new LSL_List();
}
/*
private string filterTextureUUIDbyRights(UUID origID, SceneObjectPart part, bool checkTaskInventory, bool returnInvName)
private string GetMaterialTextureUUIDbyRights(UUID origID, SceneObjectPart part)
{
if(checkTaskInventory)
{
lock (part.TaskInventory)
{
foreach (KeyValuePair<UUID, TaskInventoryItem> inv in part.TaskInventory)
{
if (inv.Value.AssetID == origID)
{
if(inv.Value.InvType == (int)InventoryType.Texture)
{
if(returnInvName)
return inv.Value.Name;
else
return origID.ToString();
}
else
return UUID.Zero.ToString();
}
}
}
}
if(World.Permissions.CanEditObject(m_host.ParentGroup.UUID, m_host.ParentGroup.RootPart.OwnerID))
return origID.ToString();
lock(part.TaskInventory)
{
foreach(KeyValuePair<UUID, TaskInventoryItem> inv in part.TaskInventory)
{
if(inv.Value.InvType == (int)InventoryType.Texture && inv.Value.AssetID == origID)
return origID.ToString();
}
}
return UUID.Zero.ToString();
}
*/
private void getLSLFaceMaterial(ref LSL_List res, int code, SceneObjectPart part, Primitive.TextureEntryFace texface)
{
UUID matID = texface.MaterialID;
UUID matID = UUID.Zero;
if(m_materialsModule != null)
matID = texface.MaterialID;
if(matID != UUID.Zero)
{
AssetBase MatAsset = World.AssetService.Get(matID.ToString());
if(MatAsset != null)
FaceMaterial mat = m_materialsModule.GetMaterial(matID);
if(mat != null)
{
Byte[] data = MatAsset.Data;
OSDMap osdmat = (OSDMap)OSDParser.DeserializeLLSDXml(data);
if(osdmat != null && osdmat.ContainsKey("NormMap"))
if(code == ScriptBaseClass.PRIM_NORMAL)
{
string mapIDstr;
FaceMaterial mat = new FaceMaterial(matID, osdmat);
if(code == ScriptBaseClass.PRIM_NORMAL)
{
// mapIDstr = filterTextureUUIDbyRights(mat.NormalMapID, part, true, false);
mapIDstr = mat.NormalMapID.ToString();
res.Add(new LSL_String(mapIDstr));
res.Add(new LSL_Vector(mat.NormalRepeatX, mat.NormalRepeatY, 0));
res.Add(new LSL_Vector(mat.NormalOffsetX, mat.NormalOffsetY, 0));
res.Add(new LSL_Float(mat.NormalRotation));
}
else if(code == ScriptBaseClass.PRIM_SPECULAR )
{
// mapIDstr = filterTextureUUIDbyRights(mat.SpecularMapID, part, true, false);
const float colorScale = 1.0f/255f;
mapIDstr = mat.SpecularMapID.ToString();
res.Add(new LSL_String(mapIDstr));
res.Add(new LSL_Vector(mat.SpecularRepeatX, mat.SpecularRepeatY, 0));
res.Add(new LSL_Vector(mat.SpecularOffsetX, mat.SpecularOffsetY, 0));
res.Add(new LSL_Float(mat.SpecularRotation));
res.Add(new LSL_Vector(mat.SpecularLightColor.R * colorScale,
mat.SpecularLightColor.G * colorScale,
mat.SpecularLightColor.B * colorScale));
res.Add(new LSL_Integer(mat.SpecularLightExponent));
res.Add(new LSL_Integer(mat.EnvironmentIntensity));
}
else if(code == ScriptBaseClass.PRIM_ALPHA_MODE)
{
res.Add(new LSL_Integer(mat.DiffuseAlphaMode));
res.Add(new LSL_Integer(mat.AlphaMaskCutoff));
}
return;
res.Add(new LSL_String(GetMaterialTextureUUIDbyRights(mat.NormalMapID, part)));
res.Add(new LSL_Vector(mat.NormalRepeatX, mat.NormalRepeatY, 0));
res.Add(new LSL_Vector(mat.NormalOffsetX, mat.NormalOffsetY, 0));
res.Add(new LSL_Float(mat.NormalRotation));
}
else if(code == ScriptBaseClass.PRIM_SPECULAR)
{
const float colorScale = 1.0f / 255f;
res.Add(new LSL_String(GetMaterialTextureUUIDbyRights(mat.SpecularMapID, part)));
res.Add(new LSL_Vector(mat.SpecularRepeatX, mat.SpecularRepeatY, 0));
res.Add(new LSL_Vector(mat.SpecularOffsetX, mat.SpecularOffsetY, 0));
res.Add(new LSL_Float(mat.SpecularRotation));
res.Add(new LSL_Vector(mat.SpecularLightColorR * colorScale,
mat.SpecularLightColorG * colorScale,
mat.SpecularLightColorB * colorScale));
res.Add(new LSL_Integer(mat.SpecularLightExponent));
res.Add(new LSL_Integer(mat.EnvironmentIntensity));
}
else if(code == ScriptBaseClass.PRIM_ALPHA_MODE)
{
res.Add(new LSL_Integer(mat.DiffuseAlphaMode));
res.Add(new LSL_Integer(mat.AlphaMaskCutoff));
}
return;
}
matID = UUID.Zero;
}
if(matID == UUID.Zero)
{
if(code == (int)ScriptBaseClass.PRIM_NORMAL || code == (int)ScriptBaseClass.PRIM_SPECULAR )
{
res.Add(new LSL_String(UUID.Zero.ToString()));
res.Add(new LSL_Vector(1.0, 1.0, 0));
res.Add(new LSL_Vector(0, 0, 0));
res.Add(new LSL_Float(0));
if(code == (int)ScriptBaseClass.PRIM_SPECULAR)
{
res.Add(new LSL_Vector(1.0, 1.0, 1.0));
res.Add(new LSL_Integer(51));
res.Add(new LSL_Integer(0));
}
}
else if(code == (int)ScriptBaseClass.PRIM_ALPHA_MODE)
// material not found
if(code == (int)ScriptBaseClass.PRIM_NORMAL || code == (int)ScriptBaseClass.PRIM_SPECULAR)
{
res.Add(new LSL_String(UUID.Zero.ToString()));
res.Add(new LSL_Vector(1.0, 1.0, 0));
res.Add(new LSL_Vector(0, 0, 0));
res.Add(new LSL_Float(0));
if(code == (int)ScriptBaseClass.PRIM_SPECULAR)
{
res.Add(new LSL_Integer(1));
res.Add(new LSL_Vector(1.0, 1.0, 1.0));
res.Add(new LSL_Integer(51));
res.Add(new LSL_Integer(0));
}
}
else if(code == (int)ScriptBaseClass.PRIM_ALPHA_MODE)
{
res.Add(new LSL_Integer(1));
res.Add(new LSL_Integer(0));
}
}
public LSL_List llGetPrimMediaParams(int face, LSL_List rules)

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using OpenSim.Region.Framework.Scenes;
using OpenMetaverse;
namespace OpenSim.Region.Framework.Interfaces
{
public interface IMaterialsModule
{
FaceMaterial GetMaterial(UUID ID);
FaceMaterial GetMaterialCopy(UUID ID);
UUID AddNewMaterial(FaceMaterial fm);
void RemoveMaterial(UUID id);
}
}