OSDN Git Service

Added GUI for Collada export
authorLatif Khalifa <latifer@streamgrid.net>
Fri, 9 Aug 2013 03:10:57 +0000 (05:10 +0200)
committerLatif Khalifa <latifer@streamgrid.net>
Fri, 9 Aug 2013 03:10:57 +0000 (05:10 +0200)
Added support for texture export

Radegast/Core/DAEExport.cs
Radegast/Core/RadegastInstance.cs
Radegast/GUI/Consoles/ExportCollada.Designer.cs [new file with mode: 0644]
Radegast/GUI/Consoles/ExportCollada.cs [new file with mode: 0644]
Radegast/GUI/Consoles/ExportCollada.resx [new file with mode: 0644]
Radegast/GUI/Dialogs/MainForm.cs

index f77047b..08e6c20 100755 (executable)
 
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using System.Text;
 using System.Xml;
 using System.IO;
 using System.Drawing;
-using System.Windows.Forms;
 using OpenMetaverse;
 using OpenMetaverse.Rendering;
 using OpenMetaverse.Imaging;
@@ -46,38 +44,53 @@ namespace Radegast
     {
         public string FileName { get; set; }
         public Primitive RootPrim { get; set; }
-
+        public List<Primitive> Prims = new List<Primitive>();
+        public List<FacetedMesh> MeshedPrims = new List<FacetedMesh>();
+        public List<UUID> Textures = new List<UUID>();
+        public string[] TextureNames;
+        public int ExportablePrims { get; set; }
+        public int ExportableTextures { get; set; }
+        public bool ExportTextures { get; set; }
+        public string ImageFormat { get; set; }
+        public static readonly List<UUID> BuiltInTextures = new List<UUID>() {
+            new UUID("89556747-24cb-43ed-920b-47caed15465f"), // default
+            new UUID("be293869-d0d9-0a69-5989-ad27f1946fd4"), // default sculpt 
+            new UUID("5748decc-f629-461c-9a36-a35a221fe21f"), // blank
+            new UUID("38b86f85-2575-52a9-a531-23108d8da837"), // invisible
+            new UUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"), // tranparent
+        };
         RadegastInstance Instance;
         GridClient Client { get { return Instance.Client; } }
-
         System.Globalization.CultureInfo invariant = System.Globalization.CultureInfo.InvariantCulture;
-
-        List<Primitive> Prims;
-        List<FacetedMesh> MeshedPrims;
         MeshmerizerR Mesher;
-
         XmlDocument Doc;
 
-        public DAEExport(RadegastInstance instance)
+        public event EventHandler<DAEStatutsEventArgs> Progress;
+
+        void OnProgress(string message)
+        {
+            if (Progress != null)
+            {
+                Progress(this, new DAEStatutsEventArgs(message));
+            }
+        }
+
+        public DAEExport(RadegastInstance instance, Primitive requestedPrim)
         {
             Instance = instance;
+            ImageFormat = "PNG";
             Mesher = new MeshmerizerR();
+            Init(Client.Network.CurrentSim, requestedPrim);
         }
 
         public void Dispose()
         {
         }
 
-        public void Export(Simulator sim, Primitive requestedPrim)
+        public void Init(Simulator sim, Primitive requestedPrim)
         {
             if (requestedPrim == null || !Client.Network.Connected) return;
 
-            if (Instance.MainForm.InvokeRequired)
-            {
-                Instance.MainForm.BeginInvoke(new MethodInvoker(() => Export(sim, requestedPrim)));
-                return;
-            }
-
             RootPrim = requestedPrim;
 
             if (requestedPrim.ParentID != 0)
@@ -89,7 +102,7 @@ namespace Radegast
                 }
             }
 
-            Prims = new List<Primitive>();
+            Prims.Clear();
             Primitive root = new Primitive(RootPrim);
             root.Position = Vector3.Zero;
             root.Rotation = Quaternion.Identity;
@@ -100,9 +113,48 @@ namespace Radegast
             Prims.ForEach(p => select.Add(p.LocalID));
             Client.Objects.SelectObjects(sim, select.ToArray(), true);
 
-            MeshedPrims = new List<FacetedMesh>(Prims.Count);
+            OnProgress("Checking permissions");
+            ExportablePrims = 0;
+            for (int i = 0; i < Prims.Count; i++)
+            {
+                if (!CanExport(Prims[i])) continue;
+                ExportablePrims++;
+
+                var defaultTexture = Prims[i].Textures.DefaultTexture;
+                if (defaultTexture != null && !Textures.Contains(defaultTexture.TextureID))
+                {
+                    Textures.Add(defaultTexture.TextureID);
+                }
+                for (int j = 0; j < Prims[i].Textures.FaceTextures.Length; j++)
+                {
+                    var te = Prims[i].Textures.FaceTextures[j];
+                    if (te == null) continue;
+                    UUID id = te.TextureID;
+                    if (!Textures.Contains(id))
+                    {
+                        Textures.Add(id);
+                    }
+                }
+            }
+
+            TextureNames = new string[Textures.Count];
+            ExportableTextures = 0;
+            for (int i = 0; i < Textures.Count; i++)
+            {
+                string name;
+                if (CanExportTexture(Textures[i], out name))
+                {
+                    ExportableTextures++;
+                    TextureNames[i] = RadegastInstance.SafeFileName(name).Replace(' ', '_');
+                }
+            }
+        }
+
+        public void Export(string Filename)
+        {
+            this.FileName = Filename;
 
-            FileName = PickFileName();
+            MeshedPrims.Clear();
 
             if (string.IsNullOrEmpty(FileName))
             {
@@ -111,8 +163,11 @@ namespace Radegast
 
             WorkPool.QueueUserWorkItem(sync =>
             {
-
-                for (int i = 0; i < Prims.Count(); i++)
+                if (ExportTextures)
+                {
+                    SaveTextures();
+                }
+                for (int i = 0; i < Prims.Count; i++)
                 {
                     if (!CanExport(Prims[i])) continue;
 
@@ -152,10 +207,88 @@ namespace Radegast
                 }
                 GenerateCollada();
                 File.WriteAllText(FileName, DocToString(Doc));
-                Instance.MainForm.AddNotification(new ntfGeneric(Instance, msg));
+                OnProgress(msg);
             });
         }
 
+        void SaveTextures()
+        {
+            OnProgress("Exporting textures...");
+            for (int i = 0; i < Textures.Count; i++)
+            {
+                var id = Textures[i];
+                if (TextureNames[i] == null)
+                {
+                    OnProgress("Skipping " + id.ToString() + " due to insufficient permissions");
+                    continue;
+                }
+
+                string filename = TextureNames[i] + "." + ImageFormat.ToLower();
+
+                OnProgress("Fetching texture" + id);
+
+                ManagedImage mImage = null;
+                Image wImage = null;
+                byte[] jpegData = null;
+
+                try
+                {
+                    System.Threading.AutoResetEvent gotImage = new System.Threading.AutoResetEvent(false);
+                    Client.Assets.RequestImage(id, ImageType.Normal, (state, asset) =>
+                    {
+                        if (state == TextureRequestState.Finished && asset != null)
+                        {
+                            jpegData = asset.AssetData;
+                            OpenJPEG.DecodeToImage(jpegData, out mImage, out wImage);
+                            gotImage.Set();
+                        }
+                        else if (state != TextureRequestState.Pending && state != TextureRequestState.Started && state != TextureRequestState.Progress)
+                        {
+                            gotImage.Set();
+                        }
+                    });
+                    gotImage.WaitOne(120 * 1000, false);
+
+                    if (wImage != null)
+                    {
+                        string fullFileName = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(FileName), filename);
+                        switch (ImageFormat)
+                        {
+                            case "PNG":
+                                wImage.Save(fullFileName, System.Drawing.Imaging.ImageFormat.Png);
+                                break;
+                            case "JPG":
+                                wImage.Save(fullFileName, System.Drawing.Imaging.ImageFormat.Jpeg);
+                                break;
+                            case "BMP":
+                                wImage.Save(fullFileName, System.Drawing.Imaging.ImageFormat.Bmp);
+                                break;
+                            case "J2C":
+                                File.WriteAllBytes(fullFileName, jpegData);
+                                break;
+                            case "TGA":
+                                File.WriteAllBytes(fullFileName, mImage.ExportTGA());
+                                break;
+                            default:
+                                throw new Exception("Unsupported image format");
+                        }
+                        OnProgress("Saved to " + fullFileName);
+                    }
+                    else
+                    {
+                        throw new Exception("Failed to decode image");
+                    }
+
+                }
+                catch (Exception ex)
+                {
+                    OnProgress("Failed: " + ex.ToString());
+                    TextureNames[i] = null;
+                }
+
+            }
+        }
+
         bool CanExport(Primitive prim)
         {
             if (prim.Properties == null) return false;
@@ -165,6 +298,43 @@ namespace Radegast
                 Instance.advancedDebugging;
         }
 
+        bool CanExportTexture(UUID id, out string name)
+        {
+            name = id.ToString();
+            if (BuiltInTextures.Contains(id))
+            {
+                return true;
+            }
+
+            InventoryItem item = null;
+            foreach (var pair in Client.Inventory.Store.Items)
+            {
+                if (pair.Value.Data is InventoryItem)
+                {
+                    var i = (InventoryItem)pair.Value.Data;
+                    if (i.AssetUUID == id && (InventoryConsole.IsFullPerm(i) || Instance.advancedDebugging))
+                    {
+                        item = i;
+                        break;
+                    }
+                }
+            }
+
+            if (item != null)
+            {
+                name = item.Name;
+                return true;
+            }
+            else if (Instance.advancedDebugging)
+            {
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
         FacetedMesh MeshPrim(Primitive prim)
         {
             FacetedMesh mesh = null;
@@ -241,33 +411,6 @@ namespace Radegast
             }
         }
 
-        string PickFileName()
-        {
-            SaveFileDialog dlg = new SaveFileDialog();
-            dlg.AddExtension = true;
-            dlg.RestoreDirectory = true;
-            dlg.Title = "Save object as...";
-            dlg.Filter = "Collada (*.dae)|*.dae";
-
-            if (RootPrim.Properties != null && !string.IsNullOrEmpty(RootPrim.Properties.Name))
-            {
-                dlg.FileName = RadegastInstance.SafeFileName(RootPrim.Properties.Name) + ".dae";
-            }
-            else
-            {
-                dlg.FileName = "Object.dae";
-            }
-
-            if (dlg.ShowDialog() == DialogResult.OK)
-            {
-                return dlg.FileName;
-            }
-            else
-            {
-                return string.Empty;
-            }
-        }
-
         XmlNode ColladaInit()
         {
             Doc = new XmlDocument();
@@ -389,9 +532,24 @@ namespace Radegast
             polylist.Attributes.Append(Doc.CreateAttribute("count")).InnerText = num_tris.ToString();
         }
 
+        void GenerateImagesSection(XmlNode images)
+        {
+            for (int i = 0; i < TextureNames.Length; i++)
+            {
+                string name = TextureNames[i];
+                if (name == null) continue;
+                string colladaName = name + "_" + ImageFormat.ToLower();
+                var image = images.AppendChild(Doc.CreateElement("image"));
+                image.Attributes.Append(Doc.CreateAttribute("id")).InnerText = colladaName;
+                image.Attributes.Append(Doc.CreateAttribute("name")).InnerText = colladaName;
+                image.AppendChild(Doc.CreateElement("init_from")).InnerText = System.Web.HttpUtility.UrlEncode(name + "." + ImageFormat.ToLower());
+            }
+        }
+
         void GenerateCollada()
         {
             var root = ColladaInit();
+            var images = root.AppendChild(Doc.CreateElement("library_images"));
             var geomLib = root.AppendChild(Doc.CreateElement("library_geometries"));
             var effects = root.AppendChild(Doc.CreateElement("library_effects"));
             var materials = root.AppendChild(Doc.CreateElement("library_materials"));
@@ -399,6 +557,10 @@ namespace Radegast
                 .AppendChild(Doc.CreateElement("visual_scene"));
             scene.Attributes.Append(Doc.CreateAttribute("id")).InnerText = "Scene";
             scene.Attributes.Append(Doc.CreateAttribute("name")).InnerText = "Scene";
+            if (ExportTextures)
+            {
+                GenerateImagesSection(images);
+            }
 
             int prim_nr = 0;
             foreach (var obj in MeshedPrims)
@@ -460,16 +622,53 @@ namespace Radegast
                 // Effects (face color, alpha)
                 for (uint face_num = 0; face_num < num_faces; face_num++)
                 {
-                    var color = obj.Faces[(int)face_num].TextureFace.RGBA;
+                    var te = obj.Faces[(int)face_num].TextureFace;
+                    var color = te.RGBA;
                     var effect = effects.AppendChild(Doc.CreateElement("effect"));
                     effect.Attributes.Append(Doc.CreateAttribute("id")).InnerText = string.Format("{0}-f{1}-{2}", geomID, face_num, "fx");
-                    var t = effect.AppendChild(Doc.CreateElement("profile_COMMON"))
-                        .AppendChild(Doc.CreateElement("technique"));
+                    var profile = effect.AppendChild(Doc.CreateElement("profile_COMMON"));
+                    string colladaName = null;
+                    if (ExportTextures)
+                    {
+                        UUID textID = UUID.Zero;
+                        int i = 0;
+                        for (; i < Textures.Count; i++)
+                        {
+                            if (te.TextureID == Textures[i])
+                            {
+                                textID = te.TextureID;
+                                break;
+                            }
+                        }
+
+                        if (textID != UUID.Zero && TextureNames[i] != null)
+                        {
+                            colladaName = TextureNames[i] + "_" + ImageFormat.ToLower();
+                            var newparam = profile.AppendChild(Doc.CreateElement("newparam"));
+                            newparam.Attributes.Append(Doc.CreateAttribute("sid")).InnerText = colladaName + "-surface";
+                            var surface = newparam.AppendChild(Doc.CreateElement("surface"));
+                            surface.Attributes.Append(Doc.CreateAttribute("type")).InnerText = "2D";
+                            surface.AppendChild(Doc.CreateElement("init_from")).InnerText = colladaName;
+                            newparam = profile.AppendChild(Doc.CreateElement("newparam"));
+                            newparam.Attributes.Append(Doc.CreateAttribute("sid")).InnerText = colladaName + "-sampler";
+                            newparam.AppendChild(Doc.CreateElement("sampler2D"))
+                                .AppendChild(Doc.CreateElement("source"))
+                                .InnerText = colladaName + "-surface";
+                        }
+
+                    }
+                    var t = profile.AppendChild(Doc.CreateElement("technique"));
                     t.Attributes.Append(Doc.CreateAttribute("sid")).InnerText = "common";
                     var phong = t.AppendChild(Doc.CreateElement("phong"));
 
-                    phong.AppendChild(Doc.CreateElement("diffuse"))
-                        .AppendChild(Doc.CreateElement("color"))
+                    var diffuse = phong.AppendChild(Doc.CreateElement("diffuse"));
+                    if (colladaName != null)
+                    {
+                        var txtr = diffuse.AppendChild(Doc.CreateElement("texture"));
+                        txtr.Attributes.Append(Doc.CreateAttribute("texture")).InnerText = colladaName + "-sampler";
+                        txtr.Attributes.Append(Doc.CreateAttribute("texcoord")).InnerText = colladaName;
+                    }
+                    diffuse.AppendChild(Doc.CreateElement("color"))
                         .InnerText = string.Format("{0} {1} {2} {3}",
                         color.R.ToString(invariant),
                         color.G.ToString(invariant),
@@ -559,4 +758,14 @@ namespace Radegast
             return ret;
         }
     }
+
+    public class DAEStatutsEventArgs : EventArgs
+    {
+        public string Message;
+
+        public DAEStatutsEventArgs(string message)
+        {
+            Message = message;
+        }
+    }
 }
index e74e95e..2dac368 100644 (file)
@@ -764,8 +764,7 @@ namespace Radegast
 
         void ExportDAEHander(object sender, EventArgs e)
         {
-            var exporter = new DAEExport(this);
-            exporter.Export(Client.Network.CurrentSim, (Primitive)sender);
+            MainForm.DisplayColladaConsole((Primitive)sender);
         }
 
 
diff --git a/Radegast/GUI/Consoles/ExportCollada.Designer.cs b/Radegast/GUI/Consoles/ExportCollada.Designer.cs
new file mode 100644 (file)
index 0000000..9871139
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Created by SharpDevelop.
+ * User: eumario
+ * Date: 7/18/2013
+ * Time: 4:14 PM
+ * 
+ * To change this template use Tools | Options | Coding | Edit Standard Headers.
+ */
+namespace Radegast
+{
+    partial class ExportCollada
+       {
+               /// <summary>
+               /// Designer variable used to keep track of non-visual components.
+               /// </summary>
+               private System.ComponentModel.IContainer components = null;
+               
+               /// <summary>
+               /// Disposes resources used by the control.
+               /// </summary>
+               /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+               protected override void Dispose(bool disposing)
+               {
+                       if (disposing) {
+                               if (components != null) {
+                                       components.Dispose();
+                               }
+                       }
+                       base.Dispose(disposing);
+               }
+               
+               /// <summary>
+               /// This method is required for Windows Forms designer support.
+               /// Do not change the method contents inside the source code editor. The Forms designer might
+               /// not be able to load this method if it was changed manually.
+               /// </summary>
+               private void InitializeComponent()
+               {
+            this.btnExport = new System.Windows.Forms.Button();
+            this.groupBox2 = new System.Windows.Forms.GroupBox();
+            this.btnBrowse = new System.Windows.Forms.Button();
+            this.txtFileName = new System.Windows.Forms.TextBox();
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.exportableTextures = new System.Windows.Forms.Label();
+            this.label7 = new System.Windows.Forms.Label();
+            this.exportablePrims = new System.Windows.Forms.Label();
+            this.label6 = new System.Windows.Forms.Label();
+            this.textureCount = new System.Windows.Forms.Label();
+            this.label4 = new System.Windows.Forms.Label();
+            this.primCount = new System.Windows.Forms.Label();
+            this.label3 = new System.Windows.Forms.Label();
+            this.objectUUID = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.objectName = new System.Windows.Forms.Label();
+            this.label1 = new System.Windows.Forms.Label();
+            this.cbExportTextures = new System.Windows.Forms.CheckBox();
+            this.groupBox3 = new System.Windows.Forms.GroupBox();
+            this.txtLog = new System.Windows.Forms.TextBox();
+            this.texturesPanel = new System.Windows.Forms.FlowLayoutPanel();
+            this.groupBox4 = new System.Windows.Forms.GroupBox();
+            this.cbImageType = new System.Windows.Forms.ComboBox();
+            this.groupBox2.SuspendLayout();
+            this.groupBox1.SuspendLayout();
+            this.groupBox3.SuspendLayout();
+            this.groupBox4.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // btnExport
+            // 
+            this.btnExport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnExport.Enabled = false;
+            this.btnExport.Location = new System.Drawing.Point(540, 377);
+            this.btnExport.Name = "btnExport";
+            this.btnExport.Size = new System.Drawing.Size(75, 23);
+            this.btnExport.TabIndex = 3;
+            this.btnExport.Text = "Export";
+            this.btnExport.UseVisualStyleBackColor = true;
+            this.btnExport.Click += new System.EventHandler(this.BtnExportClick);
+            // 
+            // groupBox2
+            // 
+            this.groupBox2.AutoSize = true;
+            this.groupBox2.Controls.Add(this.btnBrowse);
+            this.groupBox2.Controls.Add(this.txtFileName);
+            this.groupBox2.Dock = System.Windows.Forms.DockStyle.Top;
+            this.groupBox2.Location = new System.Drawing.Point(0, 0);
+            this.groupBox2.Name = "groupBox2";
+            this.groupBox2.Size = new System.Drawing.Size(621, 63);
+            this.groupBox2.TabIndex = 5;
+            this.groupBox2.TabStop = false;
+            this.groupBox2.Text = "Export To File";
+            // 
+            // btnBrowse
+            // 
+            this.btnBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnBrowse.Location = new System.Drawing.Point(540, 21);
+            this.btnBrowse.Name = "btnBrowse";
+            this.btnBrowse.Size = new System.Drawing.Size(75, 23);
+            this.btnBrowse.TabIndex = 1;
+            this.btnBrowse.Text = "Browse";
+            this.btnBrowse.UseVisualStyleBackColor = true;
+            this.btnBrowse.Click += new System.EventHandler(this.BtnBrowseClick);
+            // 
+            // txtFileName
+            // 
+            this.txtFileName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtFileName.Location = new System.Drawing.Point(8, 24);
+            this.txtFileName.Name = "txtFileName";
+            this.txtFileName.Size = new System.Drawing.Size(526, 20);
+            this.txtFileName.TabIndex = 0;
+            this.txtFileName.TextChanged += new System.EventHandler(this.TxtFileNameTextChanged);
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.AutoSize = true;
+            this.groupBox1.Controls.Add(this.exportableTextures);
+            this.groupBox1.Controls.Add(this.label7);
+            this.groupBox1.Controls.Add(this.exportablePrims);
+            this.groupBox1.Controls.Add(this.label6);
+            this.groupBox1.Controls.Add(this.textureCount);
+            this.groupBox1.Controls.Add(this.label4);
+            this.groupBox1.Controls.Add(this.primCount);
+            this.groupBox1.Controls.Add(this.label3);
+            this.groupBox1.Controls.Add(this.objectUUID);
+            this.groupBox1.Controls.Add(this.label2);
+            this.groupBox1.Controls.Add(this.objectName);
+            this.groupBox1.Controls.Add(this.label1);
+            this.groupBox1.Location = new System.Drawing.Point(0, 63);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(275, 129);
+            this.groupBox1.TabIndex = 6;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "Object Information";
+            // 
+            // exportableTextures
+            // 
+            this.exportableTextures.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.exportableTextures.Location = new System.Drawing.Point(94, 96);
+            this.exportableTextures.Name = "exportableTextures";
+            this.exportableTextures.Size = new System.Drawing.Size(175, 17);
+            this.exportableTextures.TabIndex = 11;
+            this.exportableTextures.Text = "0";
+            this.exportableTextures.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label7
+            // 
+            this.label7.Location = new System.Drawing.Point(6, 96);
+            this.label7.Name = "label7";
+            this.label7.Size = new System.Drawing.Size(82, 17);
+            this.label7.TabIndex = 10;
+            this.label7.Text = "Exportable:";
+            this.label7.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // exportablePrims
+            // 
+            this.exportablePrims.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.exportablePrims.Location = new System.Drawing.Point(94, 64);
+            this.exportablePrims.Name = "exportablePrims";
+            this.exportablePrims.Size = new System.Drawing.Size(175, 17);
+            this.exportablePrims.TabIndex = 9;
+            this.exportablePrims.Text = "label4";
+            this.exportablePrims.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label6
+            // 
+            this.label6.Location = new System.Drawing.Point(6, 64);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(82, 17);
+            this.label6.TabIndex = 8;
+            this.label6.Text = "Exportable:";
+            this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // textureCount
+            // 
+            this.textureCount.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.textureCount.Location = new System.Drawing.Point(94, 81);
+            this.textureCount.Name = "textureCount";
+            this.textureCount.Size = new System.Drawing.Size(175, 15);
+            this.textureCount.TabIndex = 7;
+            this.textureCount.Text = "label5";
+            // 
+            // label4
+            // 
+            this.label4.Location = new System.Drawing.Point(6, 79);
+            this.label4.Name = "label4";
+            this.label4.Size = new System.Drawing.Size(82, 17);
+            this.label4.TabIndex = 6;
+            this.label4.Text = "Texture Count:";
+            this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // primCount
+            // 
+            this.primCount.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.primCount.Location = new System.Drawing.Point(94, 47);
+            this.primCount.Name = "primCount";
+            this.primCount.Size = new System.Drawing.Size(175, 17);
+            this.primCount.TabIndex = 5;
+            this.primCount.Text = "label4";
+            this.primCount.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label3
+            // 
+            this.label3.Location = new System.Drawing.Point(6, 47);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(82, 17);
+            this.label3.TabIndex = 4;
+            this.label3.Text = "Prim Count:";
+            this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // objectUUID
+            // 
+            this.objectUUID.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.objectUUID.Location = new System.Drawing.Point(94, 32);
+            this.objectUUID.Name = "objectUUID";
+            this.objectUUID.Size = new System.Drawing.Size(175, 15);
+            this.objectUUID.TabIndex = 3;
+            this.objectUUID.Text = "label3";
+            this.objectUUID.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label2
+            // 
+            this.label2.Location = new System.Drawing.Point(6, 32);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(82, 15);
+            this.label2.TabIndex = 2;
+            this.label2.Text = "Object UUID:";
+            this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // objectName
+            // 
+            this.objectName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.objectName.Location = new System.Drawing.Point(94, 16);
+            this.objectName.Name = "objectName";
+            this.objectName.Size = new System.Drawing.Size(175, 16);
+            this.objectName.TabIndex = 1;
+            this.objectName.Text = "label2";
+            this.objectName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label1
+            // 
+            this.label1.Location = new System.Drawing.Point(6, 16);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(82, 16);
+            this.label1.TabIndex = 0;
+            this.label1.Text = "Object Name:";
+            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // cbExportTextures
+            // 
+            this.cbExportTextures.AutoSize = true;
+            this.cbExportTextures.Location = new System.Drawing.Point(6, 19);
+            this.cbExportTextures.Name = "cbExportTextures";
+            this.cbExportTextures.Size = new System.Drawing.Size(91, 17);
+            this.cbExportTextures.TabIndex = 11;
+            this.cbExportTextures.Text = "Enable export";
+            this.cbExportTextures.UseVisualStyleBackColor = true;
+            this.cbExportTextures.CheckedChanged += new System.EventHandler(this.cbExportTextures_CheckedChanged);
+            // 
+            // groupBox3
+            // 
+            this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.groupBox3.Controls.Add(this.txtLog);
+            this.groupBox3.Location = new System.Drawing.Point(0, 289);
+            this.groupBox3.Name = "groupBox3";
+            this.groupBox3.Size = new System.Drawing.Size(621, 82);
+            this.groupBox3.TabIndex = 7;
+            this.groupBox3.TabStop = false;
+            this.groupBox3.Text = "Log";
+            // 
+            // txtLog
+            // 
+            this.txtLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtLog.Location = new System.Drawing.Point(3, 16);
+            this.txtLog.Multiline = true;
+            this.txtLog.Name = "txtLog";
+            this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+            this.txtLog.Size = new System.Drawing.Size(615, 63);
+            this.txtLog.TabIndex = 1;
+            // 
+            // texturesPanel
+            // 
+            this.texturesPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.texturesPanel.AutoScroll = true;
+            this.texturesPanel.Location = new System.Drawing.Point(278, 69);
+            this.texturesPanel.Margin = new System.Windows.Forms.Padding(0);
+            this.texturesPanel.Name = "texturesPanel";
+            this.texturesPanel.Size = new System.Drawing.Size(337, 214);
+            this.texturesPanel.TabIndex = 8;
+            // 
+            // groupBox4
+            // 
+            this.groupBox4.Controls.Add(this.cbImageType);
+            this.groupBox4.Controls.Add(this.cbExportTextures);
+            this.groupBox4.Location = new System.Drawing.Point(9, 198);
+            this.groupBox4.Name = "groupBox4";
+            this.groupBox4.Size = new System.Drawing.Size(266, 85);
+            this.groupBox4.TabIndex = 9;
+            this.groupBox4.TabStop = false;
+            this.groupBox4.Text = "Texture Options";
+            // 
+            // cbImageType
+            // 
+            this.cbImageType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cbImageType.Enabled = false;
+            this.cbImageType.FormattingEnabled = true;
+            this.cbImageType.Items.AddRange(new object[] {
+            "TGA",
+            "PNG",
+            "JPG",
+            "TGA",
+            "J2C",
+            "BMP"});
+            this.cbImageType.Location = new System.Drawing.Point(6, 42);
+            this.cbImageType.Name = "cbImageType";
+            this.cbImageType.Size = new System.Drawing.Size(128, 21);
+            this.cbImageType.TabIndex = 12;
+            // 
+            // ExportCollada
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.groupBox4);
+            this.Controls.Add(this.texturesPanel);
+            this.Controls.Add(this.groupBox3);
+            this.Controls.Add(this.groupBox1);
+            this.Controls.Add(this.groupBox2);
+            this.Controls.Add(this.btnExport);
+            this.Name = "ExportCollada";
+            this.Size = new System.Drawing.Size(621, 410);
+            this.groupBox2.ResumeLayout(false);
+            this.groupBox2.PerformLayout();
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox3.ResumeLayout(false);
+            this.groupBox3.PerformLayout();
+            this.groupBox4.ResumeLayout(false);
+            this.groupBox4.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        public System.Windows.Forms.CheckBox cbExportTextures;
+        public System.Windows.Forms.GroupBox groupBox4;
+        public System.Windows.Forms.ComboBox cbImageType;
+        public System.Windows.Forms.Button btnExport;
+        public System.Windows.Forms.TextBox txtLog;
+        public System.Windows.Forms.GroupBox groupBox3;
+        public System.Windows.Forms.TextBox txtFileName;
+        public System.Windows.Forms.Button btnBrowse;
+        public System.Windows.Forms.GroupBox groupBox2;
+        public System.Windows.Forms.Label label1;
+        public System.Windows.Forms.Label objectName;
+        public System.Windows.Forms.Label label2;
+        public System.Windows.Forms.Label objectUUID;
+        public System.Windows.Forms.Label label3;
+        public System.Windows.Forms.Label primCount;
+        public System.Windows.Forms.Label label4;
+        public System.Windows.Forms.Label textureCount;
+        public System.Windows.Forms.GroupBox groupBox1;
+        public System.Windows.Forms.Label exportablePrims;
+        public System.Windows.Forms.Label label6;
+        public System.Windows.Forms.FlowLayoutPanel texturesPanel;
+        public System.Windows.Forms.Label exportableTextures;
+        public System.Windows.Forms.Label label7;
+       }
+}
diff --git a/Radegast/GUI/Consoles/ExportCollada.cs b/Radegast/GUI/Consoles/ExportCollada.cs
new file mode 100644 (file)
index 0000000..9f30933
--- /dev/null
@@ -0,0 +1,175 @@
+// 
+// Radegast Metaverse Client
+// Copyright (c) 2009-2013, Radegast Development Team
+// All rights reserved.
+// 
+// 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 application "Radegast", 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR 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.
+//
+// $Id$
+//
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Text;
+#if (COGBOT_LIBOMV || USE_STHREADS)
+using ThreadPoolUtil;
+using Thread = ThreadPoolUtil.Thread;
+using ThreadPool = ThreadPoolUtil.ThreadPool;
+using Monitor = ThreadPoolUtil.Monitor;
+#endif
+using System.Threading;
+using System.Windows.Forms;
+using System.IO;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+using OpenMetaverse.Assets;
+using OpenMetaverse.Imaging;
+
+namespace Radegast
+{
+       public partial class ExportCollada : RadegastTabControl
+       {
+               #region Private Variables
+        DAEExport Exporter;
+               #endregion
+               
+               #region Constructor
+        public ExportCollada(RadegastInstance instance, Primitive prim)
+            : base(instance)
+               {
+                       InitializeComponent();
+            Exporter = new DAEExport(instance, prim);
+            Exporter.Progress += new EventHandler<DAEStatutsEventArgs>(Exporter_Progress);
+            UpdateInfo();
+            cbImageType.Text = "TGA";
+               }
+               #endregion
+               
+               #region Private Methods
+               void LogMessage(string format, params object[] args)
+               {
+                       if (InvokeRequired)
+                       {
+                               if (IsHandleCreated || !instance.MonoRuntime)
+                                       BeginInvoke(new MethodInvoker(() => LogMessage(format, args)));
+                               return;
+                       }
+                       txtLog.AppendText(String.Format(format + "\r\n",args));
+                       txtLog.SelectionStart = txtLog.TextLength;
+                       txtLog.ScrollToCaret();
+               }
+
+        void UpdateInfo()
+        {
+            Primitive root = Exporter.Prims[0];
+            if (root.Properties != null)
+            {
+                objectName.Text = root.Properties.Name;
+            }
+            else
+            {
+                objectName.Text = "Object";
+            }
+            objectUUID.Text = root.ID.ToString();
+            primCount.Text = Exporter.Prims.Count.ToString();
+            exportablePrims.Text = Exporter.ExportablePrims.ToString();
+            textureCount.Text = Exporter.Textures.Count.ToString();
+            exportableTextures.Text = Exporter.ExportableTextures.ToString();
+            texturesPanel.Controls.Clear();
+            foreach (UUID textureID in Exporter.Textures)
+            {
+                var img = new SLImageHandler(instance, textureID, string.Empty);
+                img.Height = 96;
+                img.Width = 96;
+                img.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+                texturesPanel.Controls.Add(img);
+            }
+        }
+               
+               void ValidatePath(string fname)
+               {
+                       string path = Path.GetDirectoryName(fname);
+                       if (Directory.Exists(path))
+                               btnExport.Enabled = true;
+                       else
+                               btnExport.Enabled = false;
+               }
+               #endregion
+               
+               #region Event Handlers
+               void TxtFileNameTextChanged(object sender, EventArgs e)
+               {
+                       ValidatePath(txtFileName.Text);
+               }
+               
+               void BtnBrowseClick(object sender, EventArgs e)
+               {
+                       SaveFileDialog dlg = new SaveFileDialog();
+                       dlg.Title = "Export Collada File";
+            dlg.Filter = "Collada (*.dae)|*.dae|All Files (*.*)|*.*";
+            if (txtFileName.Text.Trim() == string.Empty)
+            {
+                dlg.FileName = RadegastInstance.SafeFileName(objectName.Text);
+            }
+            else
+            {
+                dlg.FileName =  Path.GetFileName(txtFileName.Text);
+            }
+
+                       DialogResult res = dlg.ShowDialog();
+                       
+                       if (res == DialogResult.OK)
+                       {
+                               txtFileName.Text = dlg.FileName;
+                               ValidatePath(dlg.FileName);
+                       }
+               }
+               
+               void BtnExportClick(object sender, EventArgs e)
+               {
+            Exporter.ImageFormat = cbImageType.Text;
+            try
+            {
+                Exporter.Export(txtFileName.Text);
+            }
+            catch (Exception ex)
+            {
+                LogMessage("Export failed: {0}", ex.ToString());
+            }
+               }
+
+        private void cbExportTextures_CheckedChanged(object sender, EventArgs e)
+        {
+            Exporter.ExportTextures = cbImageType.Enabled = cbExportTextures.Checked;
+        }
+
+        void Exporter_Progress(object sender, DAEStatutsEventArgs e)
+        {
+            LogMessage(e.Message);
+        }
+        #endregion
+    }
+}
diff --git a/Radegast/GUI/Consoles/ExportCollada.resx b/Radegast/GUI/Consoles/ExportCollada.resx
new file mode 100644 (file)
index 0000000..7080a7d
--- /dev/null
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
index 07800b9..b897c61 100644 (file)
@@ -1545,6 +1545,13 @@ namespace Radegast
         
         public void DisplayExportConsole(uint localID)
         {
+            if (InvokeRequired)
+            {
+                if (IsHandleCreated || !instance.MonoRuntime)
+                    BeginInvoke(new MethodInvoker(() => DisplayExportConsole(localID)));
+                return;
+            }
+
                if (tabsConsole.TabExists("export console"))
                {
                        tabsConsole.Tabs["export console"].Close();
@@ -1568,6 +1575,23 @@ namespace Radegast
                }
         }
 
+        public void DisplayColladaConsole(Primitive prim)
+        {
+            if (InvokeRequired)
+            {
+                if (IsHandleCreated || !instance.MonoRuntime)
+                    BeginInvoke(new MethodInvoker(() => DisplayColladaConsole(prim)));
+                return;
+            }
+
+            if (tabsConsole.TabExists("collada console"))
+            {
+                tabsConsole.Tabs["collada console"].Close();
+            }
+            RadegastTab tab = tabsConsole.AddTab("collada console", "Export Collada", new ExportCollada(instance, prim));
+            tab.Select();
+        }
+
         private void regionParcelToolStripMenuItem_Click(object sender, EventArgs e)
         {
             DisplayRegionParcelConsole();