add llSetRenderMaterial (ugly code)

This commit is contained in:
UbitUmarov
2026-02-22 11:51:58 +00:00
parent 511c4c637c
commit eaed2f5b02
5 changed files with 215 additions and 2 deletions

View File

@@ -25,8 +25,9 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using OpenSim.Region.Framework.Scenes;
using OpenMetaverse;
using OpenSim.Region.Framework.Scenes;
using static OpenMetaverse.Primitive.RenderMaterials;
namespace OpenSim.Region.Framework.Interfaces
{
@@ -36,5 +37,7 @@ namespace OpenSim.Region.Framework.Interfaces
FaceMaterial GetMaterialCopy(UUID ID);
UUID AddNewMaterial(FaceMaterial fm);
void RemoveMaterial(UUID id);
bool CleanMaterialOverrides(ref RenderMaterialOverrideEntry[] overrides, int side, bool removeTransforms = false);
bool RemoveMaterialEntry(ref RenderMaterialEntry[] entries, int side);
}
}

View File

@@ -1025,7 +1025,8 @@ namespace OpenSim.Region.OptionalModules.Materials
public static readonly byte[] XMLkeyMaterialSucess = osUTF8.GetASCIIBytes("<llsd><map><key>success</key><integer>1</integer></map></llsd>\r\n");
public static readonly byte[] XMLkeyMaterialFail = osUTF8.GetASCIIBytes("<llsd><map><key>success</key><integer>0</integer></map></llsd>\r\n");
private static bool RemoveMaterialEntry(ref RenderMaterialEntry[] entries, int side)
public bool RemoveMaterialEntry(ref RenderMaterialEntry[] entries, int side)
{
if (entries is null || entries.Length == 0)
return false;
@@ -1386,5 +1387,90 @@ namespace OpenSim.Region.OptionalModules.Materials
overrides[indx].data = data;
return true;
}
public static bool ClearOverrideData(OSDMap facemat, out OSDMap changedmat)
{
if(facemat is not null && facemat.TryGetOSDArray("ti", out OSDArray transforms))
{
changedmat = new OSDMap()
{
["ti"] = transforms
};
return facemat.Count > 1;
}
changedmat = null;
return facemat is not null;
}
public bool CleanMaterialOverrides(ref RenderMaterialOverrideEntry[] overrides, int side, bool removeTransforms = false)
{
if (overrides is null || overrides.Length == 0)
return false;
bool changed = false;
if(removeTransforms && side < 0)
{
overrides = null;
return true;
}
List<RenderMaterialOverrideEntry> newoverrides = new(overrides.Length);
for(int indx = 0; indx < overrides.Length; indx++)
{
if(side >= 0 && side != overrides[indx].te_index)
{
newoverrides.Add(overrides[indx]);
}
else if (removeTransforms)
{
changed = true;
}
else
{
if(string.IsNullOrEmpty(overrides[indx].data))
{
changed = true;
continue;
}
int tiindx = overrides[indx].data.IndexOf("ti");
if(tiindx < 0)
{
changed = true;
continue;
}
StringBuilder sb = osStringBuilderCache.Acquire();
sb.Append("{'");
int brk = 0;
do
{
char c = overrides[indx].data[tiindx];
sb.Append(c);
if(c=='[')
brk++;
else if(c==']')
{
brk--;
if(brk == 0)
break;
}
tiindx++;
}
while (tiindx < overrides[indx].data.Length);
sb.Append('}');
string newdata = osStringBuilderCache.GetStringAndRelease(sb);
changed = !newdata.Equals(overrides[indx].data);
overrides[indx].data = newdata;
newoverrides.Add(overrides[indx]);
}
}
overrides = newoverrides.Count > 0 ? [.. newoverrides] : null;
return changed;
}
}
}

View File

@@ -19612,6 +19612,123 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return 0;
}
public void llSetRenderMaterial(LSL_String materialstr, LSL_Integer lsl_face)
{
if(m_materialsModule is null)
return;
if(string.IsNullOrEmpty(materialstr.m_string))
{
Error("llSetRenderMaterial", "material \"\" not found");
return;
}
int face = lsl_face.value;
bool changed;
if(UUID.ZeroString.Equals(materialstr.m_string, StringComparison.OrdinalIgnoreCase))
{
if(m_host.Shape.RenderMaterials is null || m_host.Shape.RenderMaterials.entries is null || m_host.Shape.RenderMaterials.entries.Length == 0)
return;
changed = m_materialsModule.CleanMaterialOverrides(ref m_host.Shape.RenderMaterials.overrides, face);
if(face == ScriptBaseClass.ALL_SIDES)
{
m_host.Shape.RenderMaterials.entries = null;
changed = true;
}
else
changed |= m_materialsModule.RemoveMaterialEntry(ref m_host.Shape.RenderMaterials.entries, face);
if(changed)
{
m_host.ParentGroup.HasGroupChanged = true;
m_host.ScheduleUpdate(PrimUpdateFlags.MaterialOvr | PrimUpdateFlags.FullUpdate);
m_host.TriggerScriptChangedEvent(Changed.MATERIAL);
}
return;
}
UUID matID = ScriptUtils.GetAssetIdFromItemName(m_host, materialstr.m_string, (int)AssetType.Material);
if (matID.IsZero())
{
if (!UUID.TryParse(materialstr.m_string, out matID) || matID.IsZero())
{
Error("llSetRenderMaterial", $"material \"{materialstr.m_string}\" not found");
return;
}
}
int nsides = GetNumberOfSides(m_host);
if(face >= nsides)
return;
m_host.Shape.RenderMaterials ??= new();
m_host.Shape.RenderMaterials.entries ??= new Primitive.RenderMaterials.RenderMaterialEntry[1];
changed = m_materialsModule.CleanMaterialOverrides(ref m_host.Shape.RenderMaterials.overrides, face);
if(face == ScriptBaseClass.ALL_SIDES)
{
if(m_host.Shape.RenderMaterials.entries is null || m_host.Shape.RenderMaterials.entries.Length != nsides)
{
m_host.Shape.RenderMaterials.entries = new Primitive.RenderMaterials.RenderMaterialEntry[nsides];
for (int i = 0; i < m_host.Shape.RenderMaterials.entries.Length; i++)
{
m_host.Shape.RenderMaterials.entries[i] = new()
{
te_index = (byte)i,
id = matID
};
}
changed = true;
}
else
{
for (int i = 0; i < m_host.Shape.RenderMaterials.entries.Length; i++)
{
if(matID.NotEqual(m_host.Shape.RenderMaterials.entries[i].id))
{
changed = true;
m_host.Shape.RenderMaterials.entries[i].id = matID;
}
}
}
}
else
{
int indx = 0;
for( ; indx < m_host.Shape.RenderMaterials.entries.Length; indx++)
{
if (m_host.Shape.RenderMaterials.entries[indx].te_index == face)
{
if(matID.NotEqual(m_host.Shape.RenderMaterials.entries[indx].id))
{
changed = true;
m_host.Shape.RenderMaterials.entries[indx].id = matID;
}
break;
}
}
if(indx == m_host.Shape.RenderMaterials.entries.Length)
{
Array.Resize(ref m_host.Shape.RenderMaterials.entries, m_host.Shape.RenderMaterials.entries.Length + 1);
m_host.Shape.RenderMaterials.entries[indx] = new()
{
te_index = (byte)face,
id = matID
};
changed = true;
}
}
if(changed)
{
m_host.ParentGroup.HasGroupChanged = true;
m_host.ScheduleUpdate(PrimUpdateFlags.MaterialOvr | PrimUpdateFlags.FullUpdate);
m_host.TriggerScriptChangedEvent(Changed.MATERIAL);
}
}
public LSL_Vector llWorldPosToHUD(LSL_Vector wp)
{
if(!m_host.ParentGroup.IsAttachment)

View File

@@ -537,5 +537,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
LSL_String llGetRenderMaterial(LSL_Integer face);
LSL_Integer llIsLinkGLTFMaterial(LSL_Integer linknum, LSL_Integer face);
LSL_Vector llWorldPosToHUD(LSL_Vector WorldPosition);
void llSetRenderMaterial(LSL_String material, LSL_Integer face);
}
}

View File

@@ -2899,5 +2899,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{
return m_LSL_Functions.llWorldPosToHUD(WorldPosition);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void llSetRenderMaterial(LSL_String material, LSL_Integer face)
{
m_LSL_Functions.llSetRenderMaterial(material, face);
}
}
}