using System; using System.Text; namespace libsecondlife { public abstract class Asset { private byte[] _AssetData = new byte[0]; private LLUUID _AssetID; public LLUUID AssetID { get { return _AssetID; } internal set { _AssetID = value; } } private bool _DecodeNeeded; /// /// true if the asset's properties need to be decoded /// from the asset's data byte array. /// public bool DecodeNeeded { get { return _DecodeNeeded; } } private bool _EncodeNeeded; /// /// true if the asset's data byte array needs to be /// regenerated from the asset's properties, false otherwise. /// public bool EncodeNeeded { get { return _EncodeNeeded; } } public Asset() { } public virtual void SetEncodedData(byte[] assetData) { byte[] copy = new byte[assetData.Length]; Buffer.BlockCopy(assetData, 0, copy, 0, assetData.Length); _AssetData = copy; _DecodeNeeded = true; _EncodeNeeded = false; } public void GetEncodedData(byte[] dest, int off) { EncodeIfNeeded(); Buffer.BlockCopy(_AssetData, 0, dest, off, _AssetData.Length); } public byte[] GetEncodedData() { byte[] copy = new byte[_AssetData.Length]; GetEncodedData(copy, 0); return copy; } /// /// This method signals that the AssetData byte /// array no longer corresponds to the state of the Asset. /// /// Derived classes should call this method if their properties /// change. /// /// protected void InvalidateEncodedData() { _EncodeNeeded = true; } /// /// Regenerates the AssetData array if and only if the properties /// of the class have been modified. /// /// Call this method instead of calling Encode directly. /// /// public void EncodeIfNeeded() { if (EncodeNeeded) { Encode(out _AssetData); _EncodeNeeded = false; } } /// /// Decodes the AssetData byte array, if and only if it hasn't been /// decoded before. /// /// Derived classes should call this method before returning a value in their /// properties' getters and before setting the value in their properties' setters. /// Call this method instead of calling Decode directly. /// /// public void DecodeIfNeeded() { if (DecodeNeeded) { Decode(_AssetData); _DecodeNeeded = false; } } /// /// Regenerates the AssetData byte array from the properties /// of the derived class. /// protected abstract void Encode(out byte[] newAssetData); /// /// Decodes the AssetData, placing it in appropriate properties of the derived /// class. /// protected abstract void Decode(byte[] assetData); } public class AssetNotecard : Asset { private string _Text = null; public string Text { get { DecodeIfNeeded(); return _Text; } set { DecodeIfNeeded(); _Text = value; InvalidateEncodedData(); } } protected override void Encode(out byte[] newAssetData) { newAssetData = Helpers.StringToField(_Text); } protected override void Decode(byte[] assetData) { _Text = Helpers.FieldToUTF8String(assetData); } } public class AssetScriptText : Asset { private string _Source = null; public string Source { get { DecodeIfNeeded(); return _Source; } set { DecodeIfNeeded(); _Source = value; InvalidateEncodedData(); } } protected override void Encode(out byte[] newAssetData) { newAssetData = Helpers.StringToField(_Source); } protected override void Decode(byte[] assetData) { _Source = Helpers.FieldToUTF8String(assetData); } } public class AssetScriptBinary : Asset { public AssetScriptBinary() { } protected override void Encode(out byte[] newAssetData) { SecondLife.LogStatic("AssetScriptBinary.Encode() should never be called!", Helpers.LogLevel.Error); newAssetData = new byte[0]; } protected override void Decode(byte[] assetData) { } } public class AssetTexture : Asset { // TODO: Expand this later to take a byte[] of a non-JPEG2000 image as // the unencoded source public AssetTexture() { } protected override void Encode(out byte[] newAssetData) { SecondLife.LogStatic("AssetTexture.Encode() should never be called!", Helpers.LogLevel.Error); newAssetData = new byte[0]; } protected override void Decode(byte[] assetData) { } } public class AssetObject : Asset { public AssetObject() { } public override void SetEncodedData(byte[] assetData) { throw new InventoryException("There is no encoded data to set for object assets"); } protected override void Encode(out byte[] newAssetData) { SecondLife.LogStatic("AssetObject.Encode() should never be called!", Helpers.LogLevel.Error); newAssetData = new byte[0]; } protected override void Decode(byte[] assetData) { SecondLife.LogStatic("AssetObject.Decode() should never be called!", Helpers.LogLevel.Error); } } }