Moving examples, mapgenerator, and VisualParamGenerator to Programs folder (SVN is seriously ruined still, don't check out yet)
git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@1961 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
358
Programs/examples/TestClient/Commands/Inventory/BackupCommand.cs
Normal file
358
Programs/examples/TestClient/Commands/Inventory/BackupCommand.cs
Normal file
@@ -0,0 +1,358 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.ComponentModel;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
using OpenMetaverse.TestClient;
|
||||
|
||||
namespace OpenMetaverse.TestClient
|
||||
{
|
||||
public class QueuedDownloadInfo
|
||||
{
|
||||
public LLUUID TransferID;
|
||||
public LLUUID AssetID;
|
||||
public LLUUID ItemID;
|
||||
public LLUUID TaskID;
|
||||
public LLUUID OwnerID;
|
||||
public AssetType Type;
|
||||
public string FileName;
|
||||
public DateTime WhenRequested;
|
||||
public bool IsRequested;
|
||||
|
||||
public QueuedDownloadInfo(string file, LLUUID asset, LLUUID item, LLUUID task, LLUUID owner, AssetType type)
|
||||
{
|
||||
FileName = file;
|
||||
AssetID = asset;
|
||||
ItemID = item;
|
||||
TaskID = task;
|
||||
OwnerID = owner;
|
||||
Type = type;
|
||||
TransferID = LLUUID.Zero;
|
||||
WhenRequested = DateTime.Now;
|
||||
IsRequested = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class BackupCommand : Command
|
||||
{
|
||||
/// <summary>Maximum number of transfer requests to send to the server</summary>
|
||||
private const int MAX_TRANSFERS = 10;
|
||||
|
||||
// all items here, fed by the inventory walking thread
|
||||
private Queue<QueuedDownloadInfo> PendingDownloads = new Queue<QueuedDownloadInfo>();
|
||||
|
||||
// items sent to the server here
|
||||
private List<QueuedDownloadInfo> CurrentDownloads = new List<QueuedDownloadInfo>(MAX_TRANSFERS);
|
||||
|
||||
// background workers
|
||||
private BackgroundWorker BackupWorker;
|
||||
private BackgroundWorker QueueWorker;
|
||||
|
||||
// some stats
|
||||
private int TextItemsFound;
|
||||
private int TextItemsTransferred;
|
||||
private int TextItemErrors;
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// true if either of the background threads is running
|
||||
/// </summary>
|
||||
private bool BackgroundBackupRunning
|
||||
{
|
||||
get { return InventoryWalkerRunning || QueueRunnerRunning; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// true if the thread walking inventory is running
|
||||
/// </summary>
|
||||
private bool InventoryWalkerRunning
|
||||
{
|
||||
get { return BackupWorker != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// true if the thread feeding the queue to the server is running
|
||||
/// </summary>
|
||||
private bool QueueRunnerRunning
|
||||
{
|
||||
get { return QueueWorker != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns a string summarizing activity
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private string BackgroundBackupStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder sbResult = new StringBuilder();
|
||||
sbResult.AppendFormat("{0} is {1} running.", Name, BoolToNot(BackgroundBackupRunning));
|
||||
if (TextItemErrors != 0 || TextItemsFound != 0 || TextItemsTransferred != 0)
|
||||
{
|
||||
sbResult.AppendFormat("\r\n{0} : Inventory walker ( {1} running ) has found {2} items.",
|
||||
Name, BoolToNot(InventoryWalkerRunning), TextItemsFound);
|
||||
sbResult.AppendFormat("\r\n{0} : Server Transfers ( {1} running ) has transferred {2} items with {3} errors.",
|
||||
Name, BoolToNot(QueueRunnerRunning), TextItemsTransferred, TextItemErrors);
|
||||
sbResult.AppendFormat("\r\n{0} : {1} items in Queue, {2} items requested from server.",
|
||||
Name, PendingDownloads.Count, CurrentDownloads.Count);
|
||||
}
|
||||
return sbResult.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
||||
public BackupCommand(TestClient testClient)
|
||||
{
|
||||
Name = "backuptext";
|
||||
Description = "Backup inventory to a folder on your hard drive. Usage: " + Name + " [to <directory>] | [abort] | [status]";
|
||||
testClient.Assets.OnAssetReceived += new AssetManager.AssetReceivedCallback(Assets_OnAssetReceived);
|
||||
}
|
||||
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
StringBuilder sbResult = new StringBuilder();
|
||||
|
||||
if (args.Length == 1 && args[0] == "status")
|
||||
{
|
||||
return BackgroundBackupStatus;
|
||||
}
|
||||
else if (args.Length == 1 && args[0] == "abort")
|
||||
{
|
||||
if (!BackgroundBackupRunning)
|
||||
return BackgroundBackupStatus;
|
||||
|
||||
BackupWorker.CancelAsync();
|
||||
QueueWorker.CancelAsync();
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
// check status
|
||||
return BackgroundBackupStatus;
|
||||
}
|
||||
else if (args.Length != 2)
|
||||
{
|
||||
return "Usage: " + Name + " [to <directory>] | [abort] | [status]";
|
||||
}
|
||||
else if (BackgroundBackupRunning)
|
||||
{
|
||||
return BackgroundBackupStatus;
|
||||
}
|
||||
|
||||
QueueWorker = new BackgroundWorker();
|
||||
QueueWorker.WorkerSupportsCancellation = true;
|
||||
QueueWorker.DoWork += new DoWorkEventHandler(bwQueueRunner_DoWork);
|
||||
QueueWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwQueueRunner_RunWorkerCompleted);
|
||||
|
||||
QueueWorker.RunWorkerAsync();
|
||||
|
||||
BackupWorker = new BackgroundWorker();
|
||||
BackupWorker.WorkerSupportsCancellation = true;
|
||||
BackupWorker.DoWork +=new DoWorkEventHandler(bwBackup_DoWork);
|
||||
BackupWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwBackup_RunWorkerCompleted);
|
||||
|
||||
BackupWorker.RunWorkerAsync(args);
|
||||
return "Started background operations.";
|
||||
}
|
||||
|
||||
void bwQueueRunner_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
QueueWorker = null;
|
||||
Console.WriteLine(BackgroundBackupStatus);
|
||||
}
|
||||
|
||||
void bwQueueRunner_DoWork(object sender, DoWorkEventArgs e)
|
||||
{
|
||||
TextItemErrors = TextItemsTransferred = 0;
|
||||
|
||||
while (QueueWorker.CancellationPending == false)
|
||||
{
|
||||
// have any timed out?
|
||||
if (CurrentDownloads.Count > 0)
|
||||
{
|
||||
foreach (QueuedDownloadInfo qdi in CurrentDownloads)
|
||||
{
|
||||
if ((qdi.WhenRequested + TimeSpan.FromSeconds(60)) < DateTime.Now)
|
||||
{
|
||||
Logger.DebugLog(Name + ": timeout on asset " + qdi.AssetID.ToString(), Client);
|
||||
// submit request again
|
||||
qdi.TransferID = Client.Assets.RequestInventoryAsset(
|
||||
qdi.AssetID, qdi.ItemID, qdi.TaskID, qdi.OwnerID, qdi.Type, true);
|
||||
qdi.WhenRequested = DateTime.Now;
|
||||
qdi.IsRequested = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PendingDownloads.Count != 0)
|
||||
{
|
||||
// room in the server queue?
|
||||
if (CurrentDownloads.Count < MAX_TRANSFERS)
|
||||
{
|
||||
// yes
|
||||
QueuedDownloadInfo qdi = PendingDownloads.Dequeue();
|
||||
qdi.WhenRequested = DateTime.Now;
|
||||
qdi.IsRequested = true;
|
||||
qdi.TransferID = Client.Assets.RequestInventoryAsset(
|
||||
qdi.AssetID, qdi.ItemID, qdi.TaskID, qdi.OwnerID, qdi.Type, true);
|
||||
|
||||
lock (CurrentDownloads) CurrentDownloads.Add(qdi);
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrentDownloads.Count == 0 && PendingDownloads.Count == 0 && BackupWorker == null)
|
||||
{
|
||||
Logger.DebugLog(Name + ": both transfer queues empty AND inventory walking thread is done", Client);
|
||||
return;
|
||||
}
|
||||
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
void bwBackup_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
Console.WriteLine(Name + ": Inventory walking thread done.");
|
||||
BackupWorker = null;
|
||||
}
|
||||
|
||||
private void bwBackup_DoWork(object sender, DoWorkEventArgs e)
|
||||
{
|
||||
string[] args;
|
||||
|
||||
TextItemsFound = 0;
|
||||
|
||||
args = (string[]) e.Argument;
|
||||
|
||||
lock (CurrentDownloads) CurrentDownloads.Clear();
|
||||
|
||||
// FIXME:
|
||||
//Client.Inventory.RequestFolderContents(Client.Inventory.Store.RootFolder.UUID, Client.Self.AgentID,
|
||||
// true, true, false, InventorySortOrder.ByName);
|
||||
|
||||
DirectoryInfo di = new DirectoryInfo(args[1]);
|
||||
|
||||
// recurse on the root folder into the entire inventory
|
||||
BackupFolder(Client.Inventory.Store.RootNode, di.FullName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BackupFolder - recurse through the inventory nodes sending scripts and notecards to the transfer queue
|
||||
/// </summary>
|
||||
/// <param name="folder">The current leaf in the inventory tree</param>
|
||||
/// <param name="sPathSoFar">path so far, in the form @"c:\here" -- this needs to be "clean" for the current filesystem</param>
|
||||
private void BackupFolder(InventoryNode folder, string sPathSoFar)
|
||||
{
|
||||
StringBuilder sbRequests = new StringBuilder();
|
||||
|
||||
// FIXME:
|
||||
//Client.Inventory.RequestFolderContents(folder.Data.UUID, Client.Self.AgentID, true, true, false,
|
||||
// InventorySortOrder.ByName);
|
||||
|
||||
// first scan this folder for text
|
||||
foreach (InventoryNode iNode in folder.Nodes.Values)
|
||||
{
|
||||
if (BackupWorker.CancellationPending)
|
||||
return;
|
||||
if (iNode.Data is OpenMetaverse.InventoryItem)
|
||||
{
|
||||
InventoryItem ii = iNode.Data as InventoryItem;
|
||||
if (ii.AssetType == AssetType.LSLText || ii.AssetType == AssetType.Notecard)
|
||||
{
|
||||
// check permissions on scripts
|
||||
if (ii.AssetType == AssetType.LSLText)
|
||||
{
|
||||
if ((ii.Permissions.OwnerMask & PermissionMask.Modify) == PermissionMask.None)
|
||||
{
|
||||
// skip this one
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
string sExtension = (ii.AssetType == AssetType.LSLText) ? ".lsl" : ".txt";
|
||||
// make the output file
|
||||
string sPath = sPathSoFar + @"\" + MakeValid(ii.Name.Trim()) + sExtension;
|
||||
|
||||
// create the new qdi
|
||||
QueuedDownloadInfo qdi = new QueuedDownloadInfo(sPath, ii.AssetUUID, iNode.Data.UUID, LLUUID.Zero,
|
||||
Client.Self.AgentID, ii.AssetType);
|
||||
|
||||
// add it to the queue
|
||||
lock (PendingDownloads)
|
||||
{
|
||||
TextItemsFound++;
|
||||
PendingDownloads.Enqueue(qdi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now run any subfolders
|
||||
foreach (InventoryNode i in folder.Nodes.Values)
|
||||
{
|
||||
if (BackupWorker.CancellationPending)
|
||||
return;
|
||||
else if (i.Data is OpenMetaverse.InventoryFolder)
|
||||
BackupFolder(i, sPathSoFar + @"\" + MakeValid(i.Data.Name.Trim()));
|
||||
}
|
||||
}
|
||||
|
||||
private string MakeValid(string path)
|
||||
{
|
||||
// FIXME: We need to strip illegal characters out
|
||||
return path.Trim().Replace('"', '\'');
|
||||
}
|
||||
|
||||
private void Assets_OnAssetReceived(AssetDownload asset, Asset blah)
|
||||
{
|
||||
lock (CurrentDownloads)
|
||||
{
|
||||
// see if we have this in our transfer list
|
||||
QueuedDownloadInfo r = CurrentDownloads.Find(delegate(QueuedDownloadInfo q)
|
||||
{
|
||||
return q.TransferID == asset.ID;
|
||||
});
|
||||
|
||||
if (r != null && r.TransferID == asset.ID)
|
||||
{
|
||||
if (asset.Success)
|
||||
{
|
||||
// create the directory to put this in
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(r.FileName));
|
||||
|
||||
// write out the file
|
||||
File.WriteAllBytes(r.FileName, asset.AssetData);
|
||||
Logger.DebugLog(Name + " Wrote: " + r.FileName, Client);
|
||||
TextItemsTransferred++;
|
||||
}
|
||||
else
|
||||
{
|
||||
TextItemErrors++;
|
||||
Console.WriteLine("{0}: Download of asset {1} ({2}) failed with status {3}", Name, r.FileName,
|
||||
r.AssetID.ToString(), asset.Status.ToString());
|
||||
}
|
||||
|
||||
// remove the entry
|
||||
CurrentDownloads.Remove(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns blank or "not" if false
|
||||
/// </summary>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
private static string BoolToNot(bool b)
|
||||
{
|
||||
return b ? String.Empty : "not";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
|
||||
namespace OpenMetaverse.TestClient
|
||||
{
|
||||
public class BalanceCommand: Command
|
||||
{
|
||||
public BalanceCommand(TestClient testClient)
|
||||
{
|
||||
Name = "balance";
|
||||
Description = "Shows the amount of L$.";
|
||||
}
|
||||
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
System.Threading.AutoResetEvent waitBalance = new System.Threading.AutoResetEvent(false);
|
||||
AgentManager.BalanceCallback del = delegate(int balance) { waitBalance.Set(); };
|
||||
Client.Self.OnBalanceUpdated += del;
|
||||
Client.Self.RequestBalance();
|
||||
String result = "Timeout waiting for balance reply";
|
||||
if (waitBalance.WaitOne(10000, false))
|
||||
{
|
||||
result = Client.ToString() + " has L$: " + Client.Self.Balance;
|
||||
}
|
||||
Client.Self.OnBalanceUpdated -= del;
|
||||
return result;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.TestClient.Commands.Inventory.Shell
|
||||
{
|
||||
public class ChangeDirectoryCommand : Command
|
||||
{
|
||||
private InventoryManager Manager;
|
||||
private OpenMetaverse.Inventory Inventory;
|
||||
|
||||
public ChangeDirectoryCommand(TestClient client)
|
||||
{
|
||||
Name = "cd";
|
||||
Description = "Changes the current working inventory folder.";
|
||||
}
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
Manager = Client.Inventory;
|
||||
Inventory = Client.Inventory.Store;
|
||||
|
||||
if (args.Length > 1)
|
||||
return "Usage: cd [path-to-folder]";
|
||||
string pathStr = "";
|
||||
string[] path = null;
|
||||
if (args.Length == 0)
|
||||
{
|
||||
path = new string[] { "" };
|
||||
// cd without any arguments doesn't do anything.
|
||||
}
|
||||
else if (args.Length == 1)
|
||||
{
|
||||
pathStr = args[0];
|
||||
path = pathStr.Split(new char[] { '/' });
|
||||
// Use '/' as a path seperator.
|
||||
}
|
||||
InventoryFolder currentFolder = Client.CurrentDirectory;
|
||||
if (pathStr.StartsWith("/"))
|
||||
currentFolder = Inventory.RootFolder;
|
||||
|
||||
if (currentFolder == null) // We need this to be set to something.
|
||||
return "Error: Client not logged in.";
|
||||
|
||||
// Traverse the path, looking for the
|
||||
for (int i = 0; i < path.Length; ++i)
|
||||
{
|
||||
string nextName = path[i];
|
||||
if (string.IsNullOrEmpty(nextName) || nextName == ".")
|
||||
continue; // Ignore '.' and blanks, stay in the current directory.
|
||||
if (nextName == ".." && currentFolder != Inventory.RootFolder)
|
||||
{
|
||||
// If we encounter .., move to the parent folder.
|
||||
currentFolder = Inventory[currentFolder.ParentUUID] as InventoryFolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<InventoryBase> currentContents = Inventory.GetContents(currentFolder);
|
||||
// Try and find an InventoryBase with the corresponding name.
|
||||
bool found = false;
|
||||
foreach (InventoryBase item in currentContents)
|
||||
{
|
||||
// Allow lookup by UUID as well as name:
|
||||
if (item.Name == nextName || item.UUID.ToString() == nextName)
|
||||
{
|
||||
found = true;
|
||||
if (item is InventoryFolder)
|
||||
{
|
||||
currentFolder = item as InventoryFolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
return item.Name + " is not a folder.";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return nextName + " not found in " + currentFolder.Name;
|
||||
}
|
||||
}
|
||||
Client.CurrentDirectory = currentFolder;
|
||||
return "Current folder: " + currentFolder.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.TestClient
|
||||
{
|
||||
public class CreateNotecardCommand : Command
|
||||
{
|
||||
public CreateNotecardCommand(TestClient testClient)
|
||||
{
|
||||
Name = "createnotecard";
|
||||
Description = "Creates a notecard from a local text file.";
|
||||
}
|
||||
|
||||
void OnNoteUpdate(bool success, string status, LLUUID itemID, LLUUID assetID)
|
||||
{
|
||||
if (success)
|
||||
Console.WriteLine("Notecard successfully uploaded, ItemID {0} AssetID {1}", itemID, assetID);
|
||||
}
|
||||
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
if(args.Length < 1)
|
||||
return "Usage: createnotecard filename.txt";
|
||||
|
||||
string file = String.Empty;
|
||||
for (int ct = 0; ct < args.Length; ct++)
|
||||
file = file + args[ct] + " ";
|
||||
file = file.TrimEnd();
|
||||
|
||||
Console.WriteLine("Filename: {0}", file);
|
||||
if (!File.Exists(file))
|
||||
return String.Format("Filename '{0}' does not exist", file);
|
||||
|
||||
System.IO.StreamReader reader = new StreamReader(file);
|
||||
string body = reader.ReadToEnd();
|
||||
|
||||
// FIXME: Upload the notecard asset first. When that completes, call RequestCreateItem
|
||||
try
|
||||
{
|
||||
string desc = String.Format("{0} created by OpenMetaverse TestClient {1}", file, DateTime.Now);
|
||||
// create the asset
|
||||
|
||||
Client.Inventory.RequestCreateItem(Client.Inventory.FindFolderForType(AssetType.Notecard),
|
||||
file, desc, AssetType.Notecard, LLUUID.Random(), InventoryType.Notecard, PermissionMask.All,
|
||||
delegate(bool success, InventoryItem item) {
|
||||
if(success) // upload the asset
|
||||
Client.Inventory.RequestUploadNotecardAsset(CreateNotecardAsset(body), item.UUID, new InventoryManager.NotecardUploadedAssetCallback(OnNoteUpdate));
|
||||
}
|
||||
);
|
||||
return "Done";
|
||||
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Logger.Log(e.ToString(), Helpers.LogLevel.Error, Client);
|
||||
return "Error creating notecard.";
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="body"></param>
|
||||
public static byte[] CreateNotecardAsset(string body)
|
||||
{
|
||||
// Format the string body into Linden text
|
||||
string lindenText = "Linden text version 1\n";
|
||||
lindenText += "{\n";
|
||||
lindenText += "LLEmbeddedItems version 1\n";
|
||||
lindenText += "{\n";
|
||||
lindenText += "count 0\n";
|
||||
lindenText += "}\n";
|
||||
lindenText += "Text length " + body.Length + "\n";
|
||||
lindenText += body;
|
||||
lindenText += "}\n";
|
||||
|
||||
// Assume this is a string, add 1 for the null terminator
|
||||
byte[] stringBytes = System.Text.Encoding.UTF8.GetBytes(lindenText);
|
||||
byte[] assetData = new byte[stringBytes.Length]; //+ 1];
|
||||
Array.Copy(stringBytes, 0, assetData, 0, stringBytes.Length);
|
||||
|
||||
return assetData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.TestClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Inventory Example, Moves a folder to the Trash folder
|
||||
/// </summary>
|
||||
public class DeleteFolderCommand : Command
|
||||
{
|
||||
public DeleteFolderCommand(TestClient testClient)
|
||||
{
|
||||
Name = "deleteFolder";
|
||||
Description = "Moves a folder to the Trash Folder";
|
||||
}
|
||||
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
// parse the command line
|
||||
string target = String.Empty;
|
||||
for (int ct = 0; ct < args.Length; ct++)
|
||||
target = target + args[ct] + " ";
|
||||
target = target.TrimEnd();
|
||||
|
||||
// initialize results list
|
||||
List<InventoryBase> found = new List<InventoryBase>();
|
||||
try
|
||||
{
|
||||
// find the folder
|
||||
found = Client.Inventory.LocalFind(Client.Inventory.Store.RootFolder.UUID, target.Split('/'), 0, true);
|
||||
if (found.Count.Equals(1))
|
||||
{
|
||||
// move the folder to the trash folder
|
||||
Client.Inventory.MoveFolder(found[0].UUID, Client.Inventory.FindFolderForType(AssetType.TrashFolder));
|
||||
return String.Format("Moved folder {0} to Trash", found[0].Name);
|
||||
}
|
||||
}
|
||||
catch (InvalidOutfitException ex)
|
||||
{
|
||||
return "Folder Not Found: (" + ex.Message + ")";
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Imaging;
|
||||
|
||||
namespace OpenMetaverse.TestClient
|
||||
{
|
||||
public class DumpOutfitCommand : Command
|
||||
{
|
||||
List<LLUUID> OutfitAssets = new List<LLUUID>();
|
||||
AssetManager.ImageReceivedCallback ImageReceivedHandler;
|
||||
|
||||
public DumpOutfitCommand(TestClient testClient)
|
||||
{
|
||||
Name = "dumpoutfit";
|
||||
Description = "Dumps all of the textures from an avatars outfit to the hard drive. Usage: dumpoutfit [avatar-uuid]";
|
||||
ImageReceivedHandler = new AssetManager.ImageReceivedCallback(Assets_OnImageReceived);
|
||||
}
|
||||
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
return "Usage: dumpoutfit [avatar-uuid]";
|
||||
|
||||
LLUUID target;
|
||||
|
||||
if (!LLUUID.TryParse(args[0], out target))
|
||||
return "Usage: dumpoutfit [avatar-uuid]";
|
||||
|
||||
lock (Client.Network.Simulators)
|
||||
{
|
||||
for (int i = 0; i < Client.Network.Simulators.Count; i++)
|
||||
{
|
||||
Avatar targetAv;
|
||||
|
||||
targetAv = Client.Network.Simulators[i].ObjectsAvatars.Find(
|
||||
delegate(Avatar avatar)
|
||||
{
|
||||
return avatar.ID == target;
|
||||
}
|
||||
);
|
||||
|
||||
if (targetAv != null)
|
||||
{
|
||||
StringBuilder output = new StringBuilder("Downloading ");
|
||||
|
||||
lock (OutfitAssets) OutfitAssets.Clear();
|
||||
Client.Assets.OnImageReceived += ImageReceivedHandler;
|
||||
|
||||
for (int j = 0; j < targetAv.Textures.FaceTextures.Length; j++)
|
||||
{
|
||||
LLObject.TextureEntryFace face = targetAv.Textures.FaceTextures[j];
|
||||
|
||||
if (face != null)
|
||||
{
|
||||
ImageType type = ImageType.Normal;
|
||||
|
||||
switch ((AppearanceManager.TextureIndex)j)
|
||||
{
|
||||
case AppearanceManager.TextureIndex.HeadBaked:
|
||||
case AppearanceManager.TextureIndex.EyesBaked:
|
||||
case AppearanceManager.TextureIndex.UpperBaked:
|
||||
case AppearanceManager.TextureIndex.LowerBaked:
|
||||
case AppearanceManager.TextureIndex.SkirtBaked:
|
||||
type = ImageType.Baked;
|
||||
break;
|
||||
}
|
||||
|
||||
OutfitAssets.Add(face.TextureID);
|
||||
Client.Assets.RequestImage(face.TextureID, type, 100000.0f, 0);
|
||||
|
||||
output.Append(((AppearanceManager.TextureIndex)j).ToString());
|
||||
output.Append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
return output.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "Couldn't find avatar " + target.ToString();
|
||||
}
|
||||
|
||||
private void Assets_OnImageReceived(ImageDownload image, AssetTexture assetTexture)
|
||||
{
|
||||
lock (OutfitAssets)
|
||||
{
|
||||
if (OutfitAssets.Contains(image.ID))
|
||||
{
|
||||
if (image.Success)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.WriteAllBytes(image.ID.ToString() + ".jp2", image.AssetData);
|
||||
Console.WriteLine("Wrote JPEG2000 image " + image.ID.ToString() + ".jp2");
|
||||
|
||||
ManagedImage imgData;
|
||||
OpenJPEG.DecodeToImage(image.AssetData, out imgData);
|
||||
byte[] tgaFile = imgData.ExportTGA();
|
||||
File.WriteAllBytes(image.ID.ToString() + ".tga", tgaFile);
|
||||
Console.WriteLine("Wrote TGA image " + image.ID.ToString() + ".tga");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Failed to download image " + image.ID.ToString());
|
||||
}
|
||||
|
||||
OutfitAssets.Remove(image.ID);
|
||||
|
||||
if (OutfitAssets.Count == 0)
|
||||
Client.Assets.OnImageReceived -= ImageReceivedHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
|
||||
namespace OpenMetaverse.TestClient
|
||||
{
|
||||
public class ExportOutfitCommand : Command
|
||||
{
|
||||
public ExportOutfitCommand(TestClient testClient)
|
||||
{
|
||||
Name = "exportoutfit";
|
||||
Description = "Exports an avatars outfit to an xml file. Usage: exportoutfit [avataruuid] outputfile.xml";
|
||||
}
|
||||
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
LLUUID id;
|
||||
string path;
|
||||
|
||||
if (args.Length == 1)
|
||||
{
|
||||
id = Client.Self.AgentID;
|
||||
path = args[0];
|
||||
}
|
||||
else if (args.Length == 2)
|
||||
{
|
||||
if (!LLUUID.TryParse(args[0], out id))
|
||||
return "Usage: exportoutfit [avataruuid] outputfile.xml";
|
||||
path = args[1];
|
||||
}
|
||||
else
|
||||
return "Usage: exportoutfit [avataruuid] outputfile.xml";
|
||||
|
||||
lock (Client.Appearances)
|
||||
{
|
||||
if (Client.Appearances.ContainsKey(id))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.WriteAllText(path, Packet.ToXmlString(Client.Appearances[id]));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return e.ToString();
|
||||
}
|
||||
|
||||
return "Exported appearance for avatar " + id.ToString() + " to " + args[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Couldn't find an appearance for avatar " + id.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
|
||||
namespace OpenMetaverse.TestClient
|
||||
{
|
||||
public class GiveAllCommand: Command
|
||||
{
|
||||
public GiveAllCommand(TestClient testClient)
|
||||
{
|
||||
Name = "giveAll";
|
||||
Description = "Gives you all it's money.";
|
||||
}
|
||||
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
if (fromAgentID == LLUUID.Zero)
|
||||
return "Unable to send money to console. This command only works when IMed.";
|
||||
|
||||
int amount = Client.Self.Balance;
|
||||
Client.Self.GiveAvatarMoney(fromAgentID, Client.Self.Balance, "TestClient.GiveAll");
|
||||
return "Gave $" + amount + " to " + fromAgentID;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenMetaverse.TestClient.Commands.Inventory.Shell
|
||||
{
|
||||
class GiveItemCommand : Command
|
||||
{
|
||||
private InventoryManager Manager;
|
||||
private OpenMetaverse.Inventory Inventory;
|
||||
public GiveItemCommand(TestClient client)
|
||||
{
|
||||
Name = "give";
|
||||
Description = "Gives items from the current working directory to an avatar.";
|
||||
}
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
if (args.Length < 2)
|
||||
{
|
||||
return "Usage: give <agent uuid> <item1> [item2] [item3] [...]";
|
||||
}
|
||||
LLUUID dest;
|
||||
if (!LLUUID.TryParse(args[0], out dest))
|
||||
{
|
||||
return "First argument expected agent UUID.";
|
||||
}
|
||||
Manager = Client.Inventory;
|
||||
Inventory = Manager.Store;
|
||||
string ret = "";
|
||||
string nl = "\n";
|
||||
for (int i = 1; i < args.Length; ++i)
|
||||
{
|
||||
string inventoryName = args[i];
|
||||
// WARNING: Uses local copy of inventory contents, need to download them first.
|
||||
List<InventoryBase> contents = Inventory.GetContents(Client.CurrentDirectory);
|
||||
bool found = false;
|
||||
foreach (InventoryBase b in contents) {
|
||||
if (inventoryName == b.Name || inventoryName == b.UUID.ToString())
|
||||
{
|
||||
found = true;
|
||||
if (b is InventoryItem)
|
||||
{
|
||||
InventoryItem item = b as InventoryItem;
|
||||
Manager.GiveItem(item.UUID, item.Name, item.AssetType, dest, true);
|
||||
ret += "Gave " + item.Name + nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret += "Unable to give folder " + b.Name + nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
ret += "No inventory item named " + inventoryName + " found." + nl;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
|
||||
namespace OpenMetaverse.TestClient
|
||||
{
|
||||
public class ImportOutfitCommand : Command
|
||||
{
|
||||
//private uint SerialNum = 1;
|
||||
|
||||
public ImportOutfitCommand(TestClient testClient)
|
||||
{
|
||||
Name = "importoutfit";
|
||||
Description = "Imports an appearance from an xml file. Usage: importoutfit inputfile.xml";
|
||||
}
|
||||
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
return "Usage: importoutfit inputfile.xml";
|
||||
|
||||
return "LLSD packet import is under construction";
|
||||
|
||||
//try
|
||||
//{
|
||||
// Packet packet = Packet.FromXmlString((File.ReadAllText(args[0])));
|
||||
// if (packet.Type != PacketType.AvatarAppearance)
|
||||
// return "Deserialized a " + packet.Type + " packet instead of an AvatarAppearance packet";
|
||||
// AvatarAppearancePacket appearance = (AvatarAppearancePacket)packet;
|
||||
|
||||
// AgentSetAppearancePacket set = new AgentSetAppearancePacket();
|
||||
|
||||
// set.AgentData.AgentID = Client.Self.AgentID;
|
||||
// set.AgentData.SessionID = Client.Self.SessionID;
|
||||
// set.AgentData.SerialNum = SerialNum++;
|
||||
|
||||
// // HACK: Weak hack to calculate size
|
||||
// float AV_Height_Range = 2.025506f - 1.50856f;
|
||||
// float AV_Height = 1.50856f + (((float)appearance.VisualParam[25].ParamValue / 255.0f) * AV_Height_Range);
|
||||
// set.AgentData.Size = new LLVector3(0.45f, 0.6f, AV_Height);
|
||||
|
||||
// set.ObjectData.TextureEntry = appearance.ObjectData.TextureEntry;
|
||||
// set.VisualParam = new AgentSetAppearancePacket.VisualParamBlock[appearance.VisualParam.Length];
|
||||
|
||||
// int i = 0;
|
||||
// foreach (AvatarAppearancePacket.VisualParamBlock block in appearance.VisualParam)
|
||||
// {
|
||||
// set.VisualParam[i] = new AgentSetAppearancePacket.VisualParamBlock();
|
||||
// set.VisualParam[i].ParamValue = block.ParamValue;
|
||||
// i++;
|
||||
// }
|
||||
|
||||
// set.WearableData = new AgentSetAppearancePacket.WearableDataBlock[0];
|
||||
|
||||
// Client.Network.SendPacket(set);
|
||||
//}
|
||||
//catch (Exception)
|
||||
//{
|
||||
// return "Failed to import the appearance XML file, maybe it doesn't exist or is in the wrong format?";
|
||||
//}
|
||||
|
||||
//return "Imported " + args[0] + " and sent an AgentSetAppearance packet";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
|
||||
namespace OpenMetaverse.TestClient
|
||||
{
|
||||
public class InventoryCommand : Command
|
||||
{
|
||||
private Inventory Inventory;
|
||||
private InventoryManager Manager;
|
||||
|
||||
public InventoryCommand(TestClient testClient)
|
||||
{
|
||||
Name = "i";
|
||||
Description = "Prints out inventory.";
|
||||
}
|
||||
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
Manager = Client.Inventory;
|
||||
Inventory = Manager.Store;
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
InventoryFolder rootFolder = Inventory.RootFolder;
|
||||
PrintFolder(rootFolder, result, 0);
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
void PrintFolder(InventoryFolder f, StringBuilder result, int indent)
|
||||
{
|
||||
foreach (InventoryBase i in Manager.FolderContents(f.UUID, Client.Self.AgentID, true, true, InventorySortOrder.ByName, 3000))
|
||||
{
|
||||
result.AppendFormat("{0}{1} ({2})\n", new String(' ', indent * 2), i.Name, i.UUID);
|
||||
if (i is InventoryFolder)
|
||||
{
|
||||
InventoryFolder folder = (InventoryFolder)i;
|
||||
PrintFolder(folder, result, indent + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.TestClient.Commands.Inventory.Shell
|
||||
{
|
||||
public class ListContentsCommand : Command
|
||||
{
|
||||
private InventoryManager Manager;
|
||||
private OpenMetaverse.Inventory Inventory;
|
||||
public ListContentsCommand(TestClient client)
|
||||
{
|
||||
Name = "ls";
|
||||
Description = "Lists the contents of the current working inventory folder.";
|
||||
}
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
if (args.Length > 1)
|
||||
return "Usage: ls [-l]";
|
||||
bool longDisplay = false;
|
||||
if (args.Length > 0 && args[0] == "-l")
|
||||
longDisplay = true;
|
||||
|
||||
Manager = Client.Inventory;
|
||||
Inventory = Manager.Store;
|
||||
// WARNING: Uses local copy of inventory contents, need to download them first.
|
||||
List<InventoryBase> contents = Inventory.GetContents(Client.CurrentDirectory);
|
||||
string displayString = "";
|
||||
string nl = "\n"; // New line character
|
||||
// Pretty simple, just print out the contents.
|
||||
foreach (InventoryBase b in contents)
|
||||
{
|
||||
if (longDisplay)
|
||||
{
|
||||
// Generate a nicely formatted description of the item.
|
||||
// It kinda looks like the output of the unix ls.
|
||||
// starts with 'd' if the inventory is a folder, '-' if not.
|
||||
// 9 character permissions string
|
||||
// UUID of object
|
||||
// Name of object
|
||||
if (b is InventoryFolder)
|
||||
{
|
||||
InventoryFolder folder = b as InventoryFolder;
|
||||
displayString += "d--------- ";
|
||||
displayString += folder.UUID;
|
||||
displayString += " " + folder.Name;
|
||||
}
|
||||
else if (b is InventoryItem)
|
||||
{
|
||||
InventoryItem item = b as InventoryItem;
|
||||
displayString += "-";
|
||||
displayString += PermMaskString(item.Permissions.OwnerMask);
|
||||
displayString += PermMaskString(item.Permissions.GroupMask);
|
||||
displayString += PermMaskString(item.Permissions.EveryoneMask);
|
||||
displayString += " " + item.UUID;
|
||||
displayString += " " + item.Name;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
displayString += b.Name;
|
||||
}
|
||||
displayString += nl;
|
||||
}
|
||||
return displayString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a 3-character summary of the PermissionMask
|
||||
/// CMT if the mask allows copy, mod and transfer
|
||||
/// -MT if it disallows copy
|
||||
/// --T if it only allows transfer
|
||||
/// --- if it disallows everything
|
||||
/// </summary>
|
||||
/// <param name="mask"></param>
|
||||
/// <returns></returns>
|
||||
private static string PermMaskString(PermissionMask mask) {
|
||||
string str = "";
|
||||
if (((uint)mask | (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy)
|
||||
str += "C";
|
||||
else
|
||||
str += "-";
|
||||
if (((uint)mask | (uint)PermissionMask.Modify) == (uint)PermissionMask.Modify)
|
||||
str += "M";
|
||||
else
|
||||
str += "-";
|
||||
if (((uint)mask | (uint)PermissionMask.Transfer) == (uint)PermissionMask.Transfer)
|
||||
str += "T";
|
||||
else
|
||||
str += "-";
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.TestClient
|
||||
{
|
||||
public class ObjectInventoryCommand : Command
|
||||
{
|
||||
public ObjectInventoryCommand(TestClient testClient)
|
||||
{
|
||||
Name = "objectinventory";
|
||||
Description = "Retrieves a listing of items inside an object (task inventory). Usage: objectinventory [objectID]";
|
||||
}
|
||||
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
return "Usage: objectinventory [objectID]";
|
||||
|
||||
uint objectLocalID;
|
||||
LLUUID objectID;
|
||||
if (!LLUUID.TryParse(args[0], out objectID))
|
||||
return "Usage: objectinventory [objectID]";
|
||||
|
||||
Primitive found = Client.Network.CurrentSim.ObjectsPrimitives.Find(delegate(Primitive prim) { return prim.ID == objectID; });
|
||||
if (found != null)
|
||||
objectLocalID = found.LocalID;
|
||||
else
|
||||
return "Couldn't find prim " + objectID.ToString();
|
||||
|
||||
List<InventoryBase> items = Client.Inventory.GetTaskInventory(objectID, objectLocalID, 1000 * 30);
|
||||
|
||||
if (items != null)
|
||||
{
|
||||
string result = String.Empty;
|
||||
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
if (items[i] is InventoryFolder)
|
||||
{
|
||||
result += String.Format("[Folder] Name: {0}", items[i].Name) + Environment.NewLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
InventoryItem item = (InventoryItem)items[i];
|
||||
result += String.Format("[Item] Name: {0} Desc: {1} Type: {2}", item.Name, item.Description,
|
||||
item.AssetType) + Environment.NewLine;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Failed to download task inventory for " + objectLocalID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Drawing;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Capabilities;
|
||||
using OpenMetaverse.Imaging;
|
||||
|
||||
namespace OpenMetaverse.TestClient
|
||||
{
|
||||
public class UploadImageCommand : Command
|
||||
{
|
||||
AutoResetEvent UploadCompleteEvent = new AutoResetEvent(false);
|
||||
LLUUID TextureID = LLUUID.Zero;
|
||||
DateTime start;
|
||||
|
||||
public UploadImageCommand(TestClient testClient)
|
||||
{
|
||||
Name = "uploadimage";
|
||||
Description = "Upload an image to your inventory. Usage: uploadimage [inventoryname] [timeout] [filename]";
|
||||
}
|
||||
|
||||
public override string Execute(string[] args, LLUUID fromAgentID)
|
||||
{
|
||||
string inventoryName;
|
||||
uint timeout;
|
||||
string fileName;
|
||||
|
||||
if (args.Length != 3)
|
||||
return "Usage: uploadimage [inventoryname] [timeout] [filename]";
|
||||
|
||||
TextureID = LLUUID.Zero;
|
||||
inventoryName = args[0];
|
||||
fileName = args[2];
|
||||
if (!UInt32.TryParse(args[1], out timeout))
|
||||
return "Usage: uploadimage [inventoryname] [timeout] [filename]";
|
||||
|
||||
Console.WriteLine("Loading image " + fileName);
|
||||
byte[] jpeg2k = LoadImage(fileName);
|
||||
if (jpeg2k == null)
|
||||
return "Failed to compress image to JPEG2000";
|
||||
Console.WriteLine("Finished compressing image to JPEG2000, uploading...");
|
||||
start = DateTime.Now;
|
||||
DoUpload(jpeg2k, inventoryName);
|
||||
|
||||
if (UploadCompleteEvent.WaitOne((int)timeout, false))
|
||||
{
|
||||
return String.Format("Texture upload {0}: {1}", (TextureID != LLUUID.Zero) ? "succeeded" : "failed",
|
||||
TextureID);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Texture upload timed out";
|
||||
}
|
||||
}
|
||||
|
||||
private void DoUpload(byte[] UploadData, string FileName)
|
||||
{
|
||||
if (UploadData != null)
|
||||
{
|
||||
string name = System.IO.Path.GetFileNameWithoutExtension(FileName);
|
||||
|
||||
Client.Inventory.RequestCreateItemFromAsset(UploadData, name, "Uploaded with TestClient",
|
||||
AssetType.Texture, InventoryType.Texture, Client.Inventory.FindFolderForType(AssetType.Texture),
|
||||
|
||||
delegate(CapsClient client, long bytesReceived, long bytesSent, long totalBytesToReceive, long totalBytesToSend)
|
||||
{
|
||||
if (bytesSent > 0)
|
||||
Console.WriteLine(String.Format("Texture upload: {0} / {1}", bytesSent, totalBytesToSend));
|
||||
},
|
||||
|
||||
delegate(bool success, string status, LLUUID itemID, LLUUID assetID)
|
||||
{
|
||||
Console.WriteLine(String.Format(
|
||||
"RequestCreateItemFromAsset() returned: Success={0}, Status={1}, ItemID={2}, AssetID={3}",
|
||||
success, status, itemID, assetID));
|
||||
|
||||
TextureID = assetID;
|
||||
Console.WriteLine(String.Format("Upload took {0}", DateTime.Now.Subtract(start)));
|
||||
UploadCompleteEvent.Set();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] LoadImage(string fileName)
|
||||
{
|
||||
byte[] UploadData;
|
||||
string lowfilename = fileName.ToLower();
|
||||
Bitmap bitmap = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (lowfilename.EndsWith(".jp2") || lowfilename.EndsWith(".j2c"))
|
||||
{
|
||||
Image image;
|
||||
ManagedImage managedImage;
|
||||
|
||||
// Upload JPEG2000 images untouched
|
||||
UploadData = System.IO.File.ReadAllBytes(fileName);
|
||||
|
||||
OpenJPEG.DecodeToImage(UploadData, out managedImage, out image);
|
||||
bitmap = (Bitmap)image;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lowfilename.EndsWith(".tga"))
|
||||
bitmap = LoadTGAClass.LoadTGA(fileName);
|
||||
else
|
||||
bitmap = (Bitmap)System.Drawing.Image.FromFile(fileName);
|
||||
|
||||
int oldwidth = bitmap.Width;
|
||||
int oldheight = bitmap.Height;
|
||||
|
||||
if (!IsPowerOfTwo((uint)oldwidth) || !IsPowerOfTwo((uint)oldheight))
|
||||
{
|
||||
Bitmap resized = new Bitmap(256, 256, bitmap.PixelFormat);
|
||||
Graphics graphics = Graphics.FromImage(resized);
|
||||
|
||||
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode =
|
||||
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
|
||||
graphics.DrawImage(bitmap, 0, 0, 256, 256);
|
||||
|
||||
bitmap.Dispose();
|
||||
bitmap = resized;
|
||||
|
||||
oldwidth = 256;
|
||||
oldheight = 256;
|
||||
}
|
||||
|
||||
// Handle resizing to prevent excessively large images
|
||||
if (oldwidth > 1024 || oldheight > 1024)
|
||||
{
|
||||
int newwidth = (oldwidth > 1024) ? 1024 : oldwidth;
|
||||
int newheight = (oldheight > 1024) ? 1024 : oldheight;
|
||||
|
||||
Bitmap resized = new Bitmap(newwidth, newheight, bitmap.PixelFormat);
|
||||
Graphics graphics = Graphics.FromImage(resized);
|
||||
|
||||
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode =
|
||||
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
|
||||
graphics.DrawImage(bitmap, 0, 0, newwidth, newheight);
|
||||
|
||||
bitmap.Dispose();
|
||||
bitmap = resized;
|
||||
}
|
||||
|
||||
UploadData = OpenJPEG.EncodeFromImage(bitmap, false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.ToString() + " SL Image Upload ");
|
||||
return null;
|
||||
}
|
||||
return UploadData;
|
||||
}
|
||||
|
||||
private static bool IsPowerOfTwo(uint n)
|
||||
{
|
||||
return (n & (n - 1)) == 0 && n != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user