PooledList impl using only delegates

PooledList impl using only delegates

--- PooledList.cs
+++ PooledList.cs
@@ -8,6 +8,124 @@
 using Object = UnityEngine.Object;

 namespace SpaceTrader.Util {
+    [Serializable]
+    public class PooledList<TData, TComponent> : IReadOnlyList<TComponent>
+        where TComponent : Component {
+        public delegate bool FilterDelegate(TData data);
+        public delegate TComponent InstantiateDelegate(TComponent prefab, Transform parent);
+        public delegate void InitializeDelegate(TData data, TComponent item);
+
+        [SerializeField, HideInInspector]
+        private List<TComponent> pool = new List<TComponent>();
+
+        [SerializeField]
+        private TComponent prefab;
+
+        [SerializeField]
+        private Transform root;
+
+        public TComponent Prefab => this.prefab;
+        public Transform Root => this.root;
+
+        public int Count => this.pool.Count;
+
+        public IEnumerator<TComponent> GetEnumerator() {
+            return this.pool.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator() {
+            return this.GetEnumerator();
+        }
+
+        public TComponent this[int index] => this.pool[index];
+
+        public int ActiveCount {
+            get {
+                var count = 0;
+                foreach (var item in this.pool) {
+                    if (item.gameObject.activeSelf) {
+                        count += 1;
+                    }
+                }
+
+                return count;
+            }
+        }
+
+        /// <summary>
+        /// Destroy all TComponent instances under the Root's hierarchy that are not already in the pool
+        /// </summary>
+        public void CleanupRoot() {
+            if (!Application.isPlaying) {
+                Debug.LogAssertion("only call CleanupRoot in play mode");
+                return;
+            }
+
+            var instances = this.root.GetComponentsInChildren<TComponent>();
+            foreach (var instance in instances) {
+                if (!this.pool.Contains(instance)) {
+                    Object.Destroy(instance.gameObject);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Add all children that exist in the hierarchy under the Root and that are not already members of the
+        /// pool to the pool as disabled instances
+        /// </summary>
+        public void AddExistingChildren() {
+            foreach (var instance in this.root.GetComponentsInChildren<TComponent>(true)) {
+                if (this.pool.Contains(instance)) {
+                    continue;
+                }
+
+                this.pool.Add(instance);
+                instance.gameObject.SetActive(false);
+            }
+        }
+
+        public void Refresh(
+            IEnumerable<TData> source,
+            FilterDelegate filter = null,
+            InitializeDelegate initializer = null,
+            InstantiateDelegate instantiator = null
+        ) {
+            var index = 0;
+
+            foreach (var item in source) {
+                if (filter != null && !filter(item)) {
+                    continue;
+                }
+
+                TComponent component;
+                if (index < this.pool.Count) {
+                    component = this.pool[index];
+                } else {
+                    component = instantiator != null
+                        ? instantiator(this.prefab, this.root)
+                        : Object.Instantiate(this.prefab, this.root);
+                    this.pool.Add(component);
+                }
+
+                component.gameObject.SetActive(true);
+                initializer?.Invoke(item, component);
+
+                ++index;
+            }
+
+            while (index < this.pool.Count) {
+                this.pool[index].gameObject.SetActive(false);
+                ++index;
+            }
+        }
+
+        public void Clear() {
+            foreach (var item in this.pool) {
+                item.gameObject.SetActive(false);
+            }
+        }
+    }
+
     [Serializable]
     public abstract class PooledList<TData, TComponent, TSender> :
         IReadOnlyList<TComponent>


Update FormMain.cs

Update FormMain.cs

--- GitHubApi/FormMain.cs
+++ GitHubApi/FormMain.cs
@@ -557,7 +557,7 @@
     {
       if (tb != ActiveControl) return;
       var selectionIndex = tb.SelectionStart;
-      tb.Text = tb.Text.Insert(selectionIndex, Clipboard.GetText());
+      tb.SelectedText = Clipboard.GetText();
       tb.SelectionStart = selectionIndex + Clipboard.GetText().Length;
     }

@@ -807,4 +807,4 @@
       }
     }
   }
-}+}


deploying 1.6.54

deploying 1.6.54

--- GlobalAssemblyInfo.cs
+++ GlobalAssemblyInfo.cs
@@ -1,5 +1,5 @@
 using System.Reflection;

-[assembly: AssemblyVersion("1.6.52")]
-[assembly: AssemblyFileVersion("1.6.52")]
-[assembly: AssemblyTrademarkAttribute("68e1d7a9146d75acda4d8a38244b13bf47e44f77")]
+[assembly: AssemblyVersion("1.6.54")]
+[assembly: AssemblyFileVersion("1.6.54")]
+[assembly: AssemblyTrademarkAttribute("226f3586037f52a30b8284116cd16fbfb6f38dff")]


deploying 1.7.31

deploying 1.7.31

--- GlobalAssemblyInfo.cs
+++ GlobalAssemblyInfo.cs
@@ -1,5 +1,5 @@
 using System.Reflection;

-[assembly: AssemblyVersion("1.7.29")]
-[assembly: AssemblyFileVersion("1.7.29")]
-[assembly: AssemblyTrademarkAttribute("2124ec8b19066f799681a881654b80f69dc4b5b7")]
+[assembly: AssemblyVersion("1.7.31")]
+[assembly: AssemblyFileVersion("1.7.31")]
+[assembly: AssemblyTrademarkAttribute("5147719621192119d4ada62b281b2a9703d26921")]


Fix MetaLayerEvent doesn't assign float parameter to clip when it is an integer

--- Assets/Plugins/MetaSprite/Editor/MetaLayer/MetaLayerEvent.cs
+++ Assets/Plugins/MetaSprite/Editor/MetaLayer/MetaLayerEvent.cs
@@ -45,11 +45,10 @@
                         evt.stringParameter = layer.GetParamString(1);
                     } else if (paramType == LayerParamType.Number) {
                         var fval = layer.GetParamFloat(1);
+                        evt.floatParameter = fval;
                         if (fval == Math.Floor(fval)) {
                             evt.intParameter = (int) fval;
-                        } else {
-                            evt.floatParameter = fval;
-                        }
+                        }
                     }

                     events.Add(evt);


Restrict ActionCost for each card to Range(0, 2)

--- Assets/Scripts/HarryPotterUnity/Cards/Generic/GenericCard.cs
+++ Assets/Scripts/HarryPotterUnity/Cards/Generic/GenericCard.cs
@@ -58,7 +58,7 @@

         private List<ICardPlayRequirement> _playRequirements;

-        [UsedImplicitly, SerializeField]
+        [UsedImplicitly, SerializeField, Range(0, 2)]
         public int ActionCost = 1;

         private InputGatherer _inputGatherer;


Add gdc1.ibllc.com to known IB server list

--- Brokerages/InteractiveBrokers/InteractiveBrokersBrokerage.cs
+++ Brokerages/InteractiveBrokers/InteractiveBrokersBrokerage.cs
@@ -54,6 +54,7 @@
         // Source: https://ibkr.info/article/2816
         private readonly Dictionary<string, Region> _ibServerMap = new Dictionary<string, Region>
         {
+            { "gdc1.ibllc.com", Region.America },
             { "ndc1.ibllc.com", Region.America },
             { "ndc1_hb1.ibllc.com", Region.America },
             { "cdc1.ibllc.com", Region.America },


MMHashSpeedTest - count also TotalProcessorTime

--- PerfTests/MMHashSpeedTest.cs
+++ PerfTests/MMHashSpeedTest.cs
@@ -15,18 +15,21 @@
 			var seed=unchecked((uint)random.Next(int.MinValue,int.MaxValue));
 			var data=new byte[1024*1024+3];
 			random.NextBytes(data);
-			var mmHash=new MMHash32(seed);
-
+			var mmHash=new MMHash32(seed);
 			var sw=new Stopwatch();
-
+			var process=Process.GetCurrentProcess();
+			var startCpuTime=process.TotalProcessorTime;
 			sw.Start();
 			for(int i=0;i<iter;++i)
 				hash=mmHash.GetHash(data);
 			sw.Stop();
+			var stopCpuTime=process.TotalProcessorTime;
+			var cpuDiff=(stopCpuTime-startCpuTime).TotalSeconds;
 			var diff=sw.Elapsed.TotalSeconds;
 			var totalSize=data.Length*iter;
 			var speed=(totalSize/(1024*1024))/diff;
 			Console.WriteLine(string.Format("MMHash32.GetHash: {0} B in {1:##.##} S. Speed=={2:##.###} Mb/S.",totalSize,diff,speed));
+			Console.WriteLine(string.Format("MMHash32.GetHash: total processor time {0:##.###} S",cpuDiff));
 		}
 	}
 }


WPF Example - ExperimentalLifespanHandler improve DevTools detection

--- CefSharp.Wpf.Example/Handlers/ExperimentalLifespanHandler.cs
+++ CefSharp.Wpf.Example/Handlers/ExperimentalLifespanHandler.cs
@@ -2,6 +2,9 @@
 //
 // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

+using System;
+using System.Runtime.InteropServices;
+using System.Text;
 using System.Windows;
 using System.Windows.Interop;

@@ -13,6 +16,21 @@
     /// </summary>
     public class ExperimentalLifespanHandler : ILifeSpanHandler
     {
+        [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
+        private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
+
+        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
+        private static extern int GetWindowTextLength(IntPtr hWnd);
+
+        private static string GetWindowTitle(IntPtr hWnd)
+        {
+            // Allocate correct string length first
+            int length = GetWindowTextLength(hWnd);
+            var sb = new StringBuilder(length + 1);
+            GetWindowText(hWnd, sb, sb.Capacity);
+            return sb.ToString();
+        }
+
         bool ILifeSpanHandler.OnBeforePopup(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser)
         {
             //Set newBrowser to null unless your attempting to host the popup in a new instance of ChromiumWebBrowser
@@ -75,8 +93,12 @@
         {
             if (!browser.IsDisposed && browser.IsPopup)
             {
+                var windowTitle = GetWindowTitle(browser.GetHost().GetWindowHandle());
+
+                //CEF doesn't currently provide an option to determine if the new Popup is
+                //DevTools so we use a hackyworkaround to check the Window Title.
                 //DevTools is hosted in it's own popup, we don't perform any action here
-                if (!browser.MainFrame.Url.Equals("devtools://devtools/devtools_app.html"))
+                if (windowTitle != "DevTools")
                 {
                     var chromiumWebBrowser = (ChromiumWebBrowser)browserControl;


More mechanical comment/reorganization

More mechanical comment/reorganization

--- AzLogEntries.cs
+++ AzLogEntries.cs
@@ -9,7 +9,8 @@

 namespace AzLog
 {
-    // we're going to store a lot of these, so let's make them smaller
+    // we're going to store a lot of these, so let's make them smaller, more convenient that AzLogEntryEntitys
+    // (also we don't want to be bound strcitly to the azure log format)
     public class AzLogEntry
     {
         private string m_sPartition;
@@ -23,72 +24,6 @@
         private int m_nTid;
         private string m_sMessage;
         private string[] m_rgsMessageParts;
-
-        private int m_nGeneration; // this is going to pose a problem when multiple windows start at the same nGeneration -- we are likely to collide with multiple windows open, which means that they can
-        // have separate views but they might have the same nGeneration (so we will be caching lviItem's from one view and thinking they are valid for other views)
-        // the way to solve this *might* be to start each nGeneration with a random number, increasing the chances that we will not collide.
-
-        public string Partition
-        {
-            get { return m_sPartition; }
-            set { m_sPartition = value; }
-        }
-
-        public Guid RowKey
-        {
-            get { return m_guidRowKey; }
-            set { m_guidRowKey = value; }
-        }
-
-        public Int64 EventTickCount   {
-            get { return m_nEventTickCount; }
-            set { m_nEventTickCount = value; }
-        }
-        public string ApplicationName   {
-            get { return m_sAppName; }
-            set { m_sAppName = value; }
-        }
-        public string Level   {
-            get { return m_sLevel; }
-            set { m_sLevel = value; }
-        }
-
-        public int EventId   {
-            get { return m_nEventID; }
-            set { m_nEventID = value; }
-        }
-
-        public string InstanceId   {
-            get { return m_nInstanceID.ToString("X8"); }
-            set { m_nInstanceID = int.Parse(value, NumberStyles.AllowHexSpecifier); }
-        }
-        public int Pid   {
-            get { return m_nPid; }
-            set { m_nPid = value; }
-        }
-
-        public int Tid   {
-            get { return m_nTid; }
-            set { m_nTid = value; }
-        }
-
-        public string Message
-        {
-            get { return m_sMessage; }
-            set { m_sMessage = value; }
-        }
-
-        public string Message0 => m_rgsMessageParts.Length <= 0 ? null : m_rgsMessageParts[0];
-        public string Message1 => m_rgsMessageParts.Length <= 1 ? null : m_rgsMessageParts[1];
-        public string Message2 => m_rgsMessageParts.Length <= 2 ? null : m_rgsMessageParts[2];
-        public string Message3 => m_rgsMessageParts.Length <= 3 ? null : m_rgsMessageParts[3];
-        public string Message4 => m_rgsMessageParts.Length <= 4 ? null : m_rgsMessageParts[4];
-        public string Message5 => m_rgsMessageParts.Length <= 5 ? null : m_rgsMessageParts[5];
-        public string Message6 => m_rgsMessageParts.Length <= 6 ? null : m_rgsMessageParts[6];
-        public string Message7 => m_rgsMessageParts.Length <= 7 ? null : m_rgsMessageParts[7];
-        public string Message8 => m_rgsMessageParts.Length <= 8 ? null : m_rgsMessageParts[8];
-        public string Message9 => m_rgsMessageParts.Length <= 9 ? null : m_rgsMessageParts[9];
-

         public enum LogColumn : int
         {
@@ -114,57 +49,152 @@
             Message9 = 19
         };

+        private ListViewItem m_lvi; // this is valid if the requested generation matches the generation we have cached...
+
+        private int m_nGeneration;
+        // this is going to pose a problem when multiple windows start at the same nGeneration -- we are likely to collide with multiple windows open, which means that they can
+        // have separate views but they might have the same nGeneration (so we will be caching lviItem's from one view and thinking they are valid for other views)
+        // the way to solve this *might* be to start each nGeneration with a random number, increasing the chances that we will not collide.
+        // REVIEW: this might already be solved...
+
+        #region Accessors
+
+        public string Partition
+        {
+            get { return m_sPartition; }
+            set { m_sPartition = value; }
+        }
+
+        public Guid RowKey
+        {
+            get { return m_guidRowKey; }
+            set { m_guidRowKey = value; }
+        }
+
+        public Int64 EventTickCount
+        {
+            get { return m_nEventTickCount; }
+            set { m_nEventTickCount = value; }
+        }
+
+        public string ApplicationName
+        {
+            get { return m_sAppName; }
+            set { m_sAppName = value; }
+        }
+
+        public string Level
+        {
+            get { return m_sLevel; }
+            set { m_sLevel = value; }
+        }
+
+        public int EventId
+        {
+            get { return m_nEventID; }
+            set { m_nEventID = value; }
+        }
+
+        public string InstanceId
+        {
+            get { return m_nInstanceID.ToString("X8"); }
+            set { m_nInstanceID = int.Parse(value, NumberStyles.AllowHexSpecifier); }
+        }
+
+        public int Pid
+        {
+            get { return m_nPid; }
+            set { m_nPid = value; }
+        }
+
+        public int Tid
+        {
+            get { return m_nTid; }
+            set { m_nTid = value; }
+        }
+
+        public string Message
+        {
+            get { return m_sMessage; }
+            set { m_sMessage = value; }
+        }
+
+        public string Message0 => m_rgsMessageParts.Length <= 0 ? null : m_rgsMessageParts[0];
+        public string Message1 => m_rgsMessageParts.Length <= 1 ? null : m_rgsMessageParts[1];
+        public string Message2 => m_rgsMessageParts.Length <= 2 ? null : m_rgsMessageParts[2];
+        public string Message3 => m_rgsMessageParts.Length <= 3 ? null : m_rgsMessageParts[3];
+        public string Message4 => m_rgsMessageParts.Length <= 4 ? null : m_rgsMessageParts[4];
+        public string Message5 => m_rgsMessageParts.Length <= 5 ? null : m_rgsMessageParts[5];
+        public string Message6 => m_rgsMessageParts.Length <= 6 ? null : m_rgsMessageParts[6];
+        public string Message7 => m_rgsMessageParts.Length <= 7 ? null : m_rgsMessageParts[7];
+        public string Message8 => m_rgsMessageParts.Length <= 8 ? null : m_rgsMessageParts[8];
+        public string Message9 => m_rgsMessageParts.Length <= 9 ? null : m_rgsMessageParts[9];
+
         public string GetColumn(LogColumn lc)
         {
             switch (lc)
                 {
-                case LogColumn.Partition:
-                    return Partition;
-                case LogColumn.RowKey:
-                    return RowKey.ToString();
-                case LogColumn.EventTickCount:
-                    return m_nEventTickCount.ToString();
-                case LogColumn.AppName:
-                    return m_sAppName;
-                case LogColumn.Level:
-                    return m_sLevel;
-                case LogColumn.EventID:
-                    return m_nEventID.ToString();
-                case LogColumn.InstanceID:
-                    return m_nInstanceID.ToString();
-                case LogColumn.Pid:
-                    return m_nPid.ToString();
-                case LogColumn.Tid:
-                    return m_nTid.ToString();
-                case LogColumn.Message:
-                    return m_sMessage;
-                case LogColumn.Message0:
-                    return Message0;
-                case LogColumn.Message1:
-                    return Message1;
-                case LogColumn.Message2:
-                    return Message2;
-                case LogColumn.Message3:
-                    return Message3;
-                case LogColumn.Message4:
-                    return Message4;
-                case LogColumn.Message5:
-                    return Message5;
-                case LogColumn.Message6:
-                    return Message6;
-                case LogColumn.Message7:
-                    return Message7;
-                case LogColumn.Message8:
-                    return Message8;
-                case LogColumn.Message9:
-                    return Message9;
-                default:
-                    return "";
-                }
-        }
-
-        private ListViewItem m_lvi;
-
+                    case LogColumn.Partition:
+                        return Partition;
+                    case LogColumn.RowKey:
+                        return RowKey.ToString();
+                    case LogColumn.EventTickCount:
+                        return m_nEventTickCount.ToString();
+                    case LogColumn.AppName:
+                        return m_sAppName;
+                    case LogColumn.Level:
+                        return m_sLevel;
+                    case LogColumn.EventID:
+                        return m_nEventID.ToString();
+                    case LogColumn.InstanceID:
+                        return m_nInstanceID.ToString();
+                    case LogColumn.Pid:
+                        return m_nPid.ToString();
+                    case LogColumn.Tid:
+                        return m_nTid.ToString();
+                    case LogColumn.Message:
+                        return m_sMessage;
+                    case LogColumn.Message0:
+                        return Message0;
+                    case LogColumn.Message1:
+                        return Message1;
+                    case LogColumn.Message2:
+                        return Message2;
+                    case LogColumn.Message3:
+                        return Message3;
+                    case LogColumn.Message4:
+                        return Message4;
+                    case LogColumn.Message5:
+                        return Message5;
+                    case LogColumn.Message6:
+                        return Message6;
+                    case LogColumn.Message7:
+                        return Message7;
+                    case LogColumn.Message8:
+                        return Message8;
+                    case LogColumn.Message9:
+                        return Message9;
+                    default:
+                        return "";
+                }
+        }
+
+        /* L V I  F E T C H */
+        /*----------------------------------------------------------------------------
+        	%%Function: LviFetch
+        	%%Qualified: AzLog.AzLogEntry.LviFetch
+        	%%Contact: rlittle
+
+            Fetch a list view item appropriate for the given LogView.
+
+            We only cache one lvi at a time right now, which means that if two
+            windows decide to fetch the same lvi, we are going to be missing this
+            cache every single time because we will be flip-flopping between two
+            generations
+
+            TODO: Fix this by having more than one cache LVI (to support multiple
+            windows)
+        ----------------------------------------------------------------------------*/
         public ListViewItem LviFetch(int nGeneration, AzLogViewSettings azlvs)
         {
             if (m_lvi == null || m_nGeneration != nGeneration)
@@ -182,9 +212,24 @@
                 }
             return m_lvi;
         }
-        public AzLogEntry()
-        { }
-
+        #endregion
+
+        #region Construct/Destruct
+
+        public AzLogEntry() {}
+
+        /* C R E A T E */
+        /*----------------------------------------------------------------------------
+        	%%Function: Create
+        	%%Qualified: AzLog.AzLogEntry.Create
+        	%%Contact: rlittle
+
+            Create a log entry from its constituent parts. This will parse
+            sMessage into all its subparts too (split by \t).
+
+            FUTURE: If this gets too slow, we can make this "opt in" to parse the
+            message
+        ----------------------------------------------------------------------------*/
         public static AzLogEntry Create(string sPartition, Guid guidRowKey, Int64 nEventTickCount, string sAppName,
             string sLevel, int nEventId, string sInstanceId, int nPid, int nTid, string sMessage)
         {
@@ -204,25 +249,36 @@
             return azle;
         }

+        /* C R E A T E */
+        /*----------------------------------------------------------------------------
+        	%%Function: Create
+        	%%Qualified: AzLog.AzLogEntry.Create
+        	%%Contact: rlittle
+
+            Create the log entry from the Azure entity.
+        ----------------------------------------------------------------------------*/
         public static AzLogEntry Create(AzLogEntryEntity azlee)
         {
             return AzLogEntry.Create(azlee.PartitionKey, Guid.Parse(azlee.RowKey), azlee.EventTickCount,
                                      azlee.ApplicationName, azlee.Level, azlee.EventId, azlee.InstanceId, azlee.Pid,
                                      azlee.Tid, azlee.Message);
         }
+        #endregion
     }
-
+
     // We need an uber collection that supports virtualized set of AzLogEntries. Preferably partitioned. Supporting filtered and sorted views that doesn't change the underlying collection
     // we also need to know the ranges of data that are "complete", "pending", or "partial"
     // The we will use PartitionKey + RowKey as the master key for uniqueness (to allow filling of partial data)
     //
     // for now we will partition the data by day + hour (using the partitions)
-    class AzLogEntries
+    internal class AzLogEntries
     {
         // this collection must only grow and only append. all views depend on that.
         private List<AzLogEntry> m_plale;
         private AzLogParts m_azlps;

+        // the underlying length is the same regardless of the number of parts -- its just the number
+        // of log entries
         public int Length => m_plale.Count;

         public AzLogEntries()
@@ -274,9 +330,13 @@
                     }
                 }
         }
-
+
     }
-    class CompareLogEntryTickCount : IComparer<int>
+
+    // ============================================================================
+    // C O M P A R E  L O G  E N T R Y  T I C K  C O U N T
+    // ============================================================================
+    internal class CompareLogEntryTickCount : IComparer<int>
     {
         private AzLogModel m_azlm;

@@ -297,6 +357,4 @@
             return -1;
         }
     }
-
-
-}
+}


Added classes to debug output.

Added classes to debug output.

--- Perspex/Diagnostics/Debug.cs
+++ Perspex/Diagnostics/Debug.cs
@@ -3,6 +3,7 @@
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Perspex.Controls;

 namespace Perspex.Diagnostics
 {
@@ -17,6 +18,8 @@

         private static void PrintVisualTree(IVisual visual, StringBuilder builder, int indent)
         {
+            Control control = visual as Control;
+
             builder.Append(Indent(indent - 1));

             if (indent > 0)
@@ -24,13 +27,14 @@
                 builder.Append(" +- ");
             }

-            builder.AppendLine(visual.GetType().Name);
+            builder.Append(visual.GetType().Name);

-            PerspexObject p = visual as PerspexObject;
+            if (control != null)
+            {
+                builder.Append(" ");
+                builder.AppendLine(control.Classes.ToString());

-            if (p != null)
-            {
-                foreach (var value in p.GetSetValues())
+                foreach (var value in control.GetSetValues())
                 {
                     builder.Append(Indent(indent));
                     builder.Append(" |  ");
@@ -41,6 +45,10 @@
                     builder.Append(value.Item3);
                     builder.AppendLine("]");
                 }
+            }
+            else
+            {
+                builder.AppendLine();
             }

             foreach (var child in visual.VisualChildren)


Add global exception handle, not enable.

Signed-off-by: robertzml <321e7786a406a136366094c578d0f1193a3468e1@126.com>

--- Phoebe.FormClient/Program.cs
+++ Phoebe.FormClient/Program.cs
@@ -27,6 +27,7 @@
             DevExpress.Skins.SkinManager.EnableMdiFormSkins();
             Application.EnableVisualStyles();
             Application.SetCompatibleTextRenderingDefault(false);
+            //Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

             LoginForm login = new LoginForm();
             if (login.ShowDialog() == DialogResult.OK)
@@ -37,5 +38,19 @@
                 Application.Run(new MainForm());
             }
         }
+
+        /// <summary>
+        /// 异常消息处理
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="ex"></param>
+        private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs ex)
+        {
+            string message = string.Format("{0}\r\n操作发生错误，您需要退出系统么？", ex.Exception.Message);
+            if (MessageUtil.ConfirmYesNo(message) == DialogResult.Yes)
+            {
+                Application.Exit();
+            }
+        }
     }
 }


Fix bug to remove last Cursor

Fix bug to remove last Cursor

--- Pinta.Core/Tools/ZoomTool.cs
+++ Pinta.Core/Tools/ZoomTool.cs
@@ -180,6 +180,13 @@

 			return new Rectangle (x, y, w, h);
 		}
+
+		protected override void OnDeactivated ()
+		{
+			Cursor = null;
+			base.OnDeactivated ();
+		}
+

 	}
 }


Hearthstone Plugin: Fixed for Icecrown

Hearthstone Plugin: Fixed for Icecrown

--- Plugin-Hearthstone/Tables.cs
+++ Plugin-Hearthstone/Tables.cs
@@ -19,7 +19,9 @@
             {"LOE", "Year2" },
             {"OG", "Kraken" },
             {"MSG", "Kraken" },
-            {"UNGORO","Mammoth" }
+            {"KARA", "Kraken" },
+            {"UNGORO","Mammoth" },
+            {"ICECROWN","Mammoth" }
         };


Cleanup.

Cleanup.

--- Classes/SiteHelpers.cs
+++ Classes/SiteHelpers.cs
@@ -217,10 +217,11 @@
 				};
 				if (thumb.URL == null || thumb.FileName.Length == 0) continue;

-				{
-					HTMLAttribute attribute = fileTextLinkStartTag.GetAttribute("href");
-					if (attribute == null) continue;
-					if (replaceList != null) {
+				if (replaceList != null) {
+					HTMLAttribute attribute;
+
+					attribute = fileTextLinkStartTag.GetAttribute("href");
+					if (attribute != null) {
 						replaceList.Add(
 							new ReplaceInfo {
 								Offset = attribute.Offset,
@@ -229,12 +230,9 @@
 								Tag = image.FileName
 							});
 					}
-				}
-
-				{
-					HTMLAttribute attribute = fileThumbLinkStartTag.GetAttribute("href");
-					if (attribute == null) continue;
-					if (replaceList != null) {
+
+					attribute = fileThumbLinkStartTag.GetAttribute("href");
+					if (attribute != null) {
 						replaceList.Add(
 							new ReplaceInfo {
 								Offset = attribute.Offset,
@@ -243,12 +241,9 @@
 								Tag = image.FileName
 							});
 					}
-				}
-
-				{
-					HTMLAttribute attribute = fileThumbImageTag.GetAttribute("src");
-					if (attribute == null) continue;
-					if (replaceList != null) {
+
+					attribute = fileThumbImageTag.GetAttribute("src");
+					if (attribute != null) {
 						replaceList.Add(
 							new ReplaceInfo {
 								Offset = attribute.Offset,


Just do a sort

Just do a sort

--- CodePlayground/Program.cs
+++ CodePlayground/Program.cs
@@ -109,6 +109,10 @@
     {
         static void Main(string[] args)
         {
+            var sequence = SequenceFromConsole().OrderBy(s => s.Length);
+            foreach (var item in sequence)
+                Console.WriteLine($"\t{item}");
+            return;
             var sum = SequenceFromConsole().Select(s => int.Parse(s))
                 .Aggregate("Comma Separated", (existingString, item) => existingString + ", " + item);
             Console.WriteLine(sum);


Don't run update script if any files fail to download

--- Processors/FileDownloader.cs
+++ Processors/FileDownloader.cs
@@ -70,6 +70,7 @@
             var randomGenerator = new Random();
             var files = depotManifest.Files.Where(x => IsFileNameMatching(job.DepotID, x.FileName)).ToList();
             var filesUpdated = false;
+            var filesAnyFailed = false;

             var hashesFile = Path.Combine(Application.Path, "files", ".support", "hashes", string.Format("{0}.json", job.DepotID));
             var hashes = new Dictionary<string, byte[]>();
@@ -275,6 +276,8 @@
                 }
                 else
                 {
+                    filesAnyFailed = true;
+
                     IRC.Instance.SendOps("{0}[{1}]{2} Failed to download {3}: Only {4} out of {5} chunks downloaded ({6})",
                         Colors.OLIVE, Steam.GetAppName(job.ParentAppID), Colors.NORMAL, file.FileName, count, chunks.Count, lastError);

@@ -287,6 +290,14 @@

             if (filesUpdated)
             {
+                if (filesAnyFailed)
+                {
+                    IRC.Instance.SendOps("{0}[{1}]{2} Failed to download some files, not running update script to prevent broken diffs.",
+                        Colors.OLIVE, Steam.GetAppName(job.ParentAppID), Colors.NORMAL);
+
+                    return;
+                }
+
                 File.WriteAllText(hashesFile, JsonConvert.SerializeObject(hashes));

                 var updateScript = Path.Combine(Application.Path, "files", "update.sh");


:lipstick:

:lipstick:

--- Code/Nancy.SimpleErrorHandlers/JsonErrorStatusCodeHandler.cs
+++ Code/Nancy.SimpleErrorHandlers/JsonErrorStatusCodeHandler.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Text;
 using Nancy.ErrorHandling;
 using Nancy.Responses;

@@ -55,7 +56,7 @@

             viewModel.Message = exception == null
                 ? "An error has occured but no exception was provided. So we're not sure what has happened, even though something has. :/"
-                : GetlowestInnerException(exception).Message;
+                : GetLowestInnerException(exception).Message;

             var serializer = _jsonSerializer ??
                 (_jsonSerializer = _serializers.FirstOrDefault(s => s.CanSerialize("application/json")));
@@ -67,7 +68,7 @@
             context.Response = response;
         }

-        private static Exception GetlowestInnerException(Exception exception)
+        private static Exception GetLowestInnerException(Exception exception)
         {
             if (exception == null)
             {


Fix /info endpoint for when geolocation is unknown #160

--- Control/InfoController.cs
+++ Control/InfoController.cs
@@ -37,16 +37,25 @@
             Response.ContentType = MimeType.Json;
             using (var writer = HttpContext.OpenResponseText(Encoding.UTF8, true))
             {
-                writer.Write(
-                    JObject.FromObject(new
-                    {
-                        hardwareKey = ApplicationSettings.Default.HardwareKey.ToString(),
-                        displayName = ApplicationSettings.Default.DisplayName,
-                        timeZone = ApplicationSettings.Default.DisplayTimeZone,
-                        latitude = ClientInfo.Instance.CurrentGeoLocation.Latitude,
-                        longitude = ClientInfo.Instance.CurrentGeoLocation.Longitude
-                    })
-                .ToString());
+                JObject jObject = JObject.FromObject( new
+                {
+                    hardwareKey = ApplicationSettings.Default.HardwareKey.ToString(),
+                    displayName = ApplicationSettings.Default.DisplayName,
+                    timeZone = ApplicationSettings.Default.DisplayTimeZone
+                });
+
+                if (ClientInfo.Instance.CurrentGeoLocation != null && !ClientInfo.Instance.CurrentGeoLocation.IsUnknown)
+                {
+                    jObject.Add("latitude", ClientInfo.Instance.CurrentGeoLocation.Latitude);
+                    jObject.Add("longitude", ClientInfo.Instance.CurrentGeoLocation.Longitude);
+                }
+                else
+                {
+                    jObject.Add("latitude", null);
+                    jObject.Add("longitude", null);
+                }
+
+                writer.Write(jObject.ToString());
             }
         }
     }


Configurable raycast length for wall collision detection

--- Core/Motion2D/Motion2D.cs
+++ Core/Motion2D/Motion2D.cs
@@ -14,15 +14,10 @@
 	// Connetion to Rigidbody2D.velocity
 	public Vector2 velocity
 	{
-		get
-		{
-			return rbody.velocity;
-		}
-		set
-		{
-			rbody.velocity = value;
-		}
+		get { return rbody.velocity; }
+		set { rbody.velocity = value; }
 	}
+

 	[Header("Config")]
 	[Range(0, 10)] public float attack;
@@ -40,15 +35,16 @@
 	public Vector2 force;
 	public float forceLimit;

-	[Header("Walls")]
+	[Header("Walls Detection")]
+	public float raycastLength = 0.25f;
 	public LayerMask wallLayer;
 	public Vector4 wallsColliding; // Clock style; x = up, y = right, z = down, w = left

+	private float colliderRadius;

 	private Rigidbody2D rbody;
 	private Collider2D collider;
 	private Vector2 movement;
-	private float raylen;

 	void Start()
@@ -63,8 +59,8 @@
 		rbody.gravityScale = 0; // We use our own gravity

-		// Raycast length recommended
-		raylen = Mathf.Max(collider.bounds.extents.y, collider.bounds.extents.x) * 1.5f;
+		// Collider radius
+		colliderRadius = Mathf.Max(collider.bounds.extents.y, collider.bounds.extents.x);

 		this.tt("WallCollisionDetection").ttAdd(0.10f, () =>
@@ -113,10 +109,10 @@
 	{
 		Vector3 pos = transform.position;

-		wallsColliding.w = Physics2D.Raycast(pos, Vector2.left, raylen, wallLayer) ? 1 : 0;
-		wallsColliding.y = Physics2D.Raycast(pos, Vector2.right, raylen,  wallLayer) ? 1 : 0;
-		wallsColliding.x = Physics2D.Raycast(pos, Vector2.up, raylen,  wallLayer) ? 1 : 0;
-		wallsColliding.z = Physics2D.Raycast(pos, Vector2.down, raylen, wallLayer) ? 1 : 0;
+		wallsColliding.w = Physics2D.Raycast(pos, Vector2.left, colliderRadius + raycastLength, wallLayer) ? 1 : 0;
+		wallsColliding.y = Physics2D.Raycast(pos, Vector2.right, colliderRadius + raycastLength,  wallLayer) ? 1 : 0;
+		wallsColliding.x = Physics2D.Raycast(pos, Vector2.up, colliderRadius + raycastLength,  wallLayer) ? 1 : 0;
+		wallsColliding.z = Physics2D.Raycast(pos, Vector2.down, colliderRadius + raycastLength, wallLayer) ? 1 : 0;
 	}


Fix DbModelReader to only read public instance members.

--- Ctl.Core/DbModelReader.cs
+++ Ctl.Core/DbModelReader.cs
@@ -295,7 +295,7 @@

             readBody.Add(Expression.Assign(valueVar, Expression.New(t)));

-            var info = (from m in t.GetMembers()
+            var info = (from m in t.GetMembers(BindingFlags.Instance | BindingFlags.Public)
                         where m.GetCustomAttribute<NotMappedAttribute>() == null
                         let p = m as PropertyInfo
                         let f = m as FieldInfo


Fix SpawnX and SpawnY not being set on loadlevel

--- CupCake.Players/Player.cs
+++ CupCake.Players/Player.cs
@@ -352,6 +352,9 @@
                 Point location = e.Coordinates[this.UserId];
                 this.PosX = location.X;
                 this.PosY = location.Y;
+                this.SpawnX = location.X;
+                this.SpawnY = location.Y;
+
                 this.IsDead = false;

                 if (e.ResetCoins)


Decipher + bugs

Decipher + bugs

--- DES/DES/Model/DESClass.cs
+++ DES/DES/Model/DESClass.cs
@@ -140,7 +140,17 @@
             Work = builder.ToString();
             return plainBits;
         }
-
+        public string DecipherHex(int rounds = 5)
+        {
+            Plaintext = Decipher(Ciphertext.StringToByteArray(), Key.StringToByteArray(), rounds).ToByteArray().ByteArrayToStringValue();
+            return Plaintext;
+        }
+
+        public string DecipherString(int rounds = 5)
+        {
+            Plaintext = Decipher(Encoding.UTF8.GetBytes(Ciphertext), Key.StringToByteArray(), rounds).ToByteArray().ByteArrayToString();
+            return Plaintext;
+        }
         private BitArray Decipher(byte[] message, byte[] key, int rounds)
         {
             var builder = new StringBuilder();
@@ -154,8 +164,8 @@
             BitArray switchTemp;
             builder.AppendFormat("Transformed {0} text to {1} {2}", Plaintext, cipherbits.Print(), Environment.NewLine);
             builder.AppendFormat("Using key {0} with bits {1} {2}", key.ByteArrayToStringValue(), keyBits.Print(), Environment.NewLine);
-            cipherbits = InverseInitialPermutation(cipherbits);
-            builder.AppendFormat("Inverse initial permutation result {0}{1}", cipherbits.Print(), Environment.NewLine);
+            cipherbits = InitialPermutation(cipherbits);
+            builder.AppendFormat("Initial permutation result {0}{1}", cipherbits.Print(), Environment.NewLine);
             keyBits = PermutedChoiceOne(keyBits);
             builder.AppendFormat("Permuted choice one {0}{1}", keyBits.Print(), Environment.NewLine);
             for (var i = 1; i <= 64; i++) //copiar los arreglos de bit a los nuevos Array.Copy no sirve con BitArray
@@ -177,26 +187,32 @@
                     d.Bit(i - 28, keyBits.Bit(i));
                 }
             }
-            c = AllKeyShifts(c, rounds);
-            d = AllKeyShifts(d, rounds);
+            //c = AllKeyShifts(c, rounds);
+            //d = AllKeyShifts(d, rounds);
             builder.AppendFormat("Left {0}{1}", left.Print(), Environment.NewLine);
             builder.AppendFormat("Right {0}{1}", right.Print(), Environment.NewLine);
-            switchTemp = right; //para hacer el cambio de valores
+            switchTemp = right; //para hacer el cambio de valores del final
             right = left;
             left = switchTemp;
             builder.AppendFormat("Left {0}{1}", left.Print(), Environment.NewLine);
             builder.AppendFormat("Right {0}{1}", right.Print(), Environment.NewLine);
-            builder.AppendFormat("c{0} {1}{2}", rounds, c.Print(), Environment.NewLine);
-            builder.AppendFormat("d{0} {1}{2}", rounds, d.Print(), Environment.NewLine);
-
-            for (var i = rounds; i > 0; i++)
-            {
-                c = KeyRightShift(c, i);
-                d = KeyRightShift(d, i);
+            //builder.AppendFormat("c{0} {1}{2}", rounds, c.Print(), Environment.NewLine);
+            //builder.AppendFormat("d{0} {1}{2}", rounds, d.Print(), Environment.NewLine);
+
+            for (var i = rounds; i > 0; i--)
+            {
+                //if (i != rounds) //empieza con las c y d finales
+                //{
+                //    c = KeyRightShift(c, i);
+                //    d = KeyRightShift(d, i);
+                //    builder.AppendFormat("c{0} {1}{2}", i, c.Print(), Environment.NewLine);
+                //    builder.AppendFormat("d{0} {1}{2}", i, d.Print(), Environment.NewLine);
+                //}
+                c = AllKeyShifts(c, i);
+                d = AllKeyShifts(d, i);
                 builder.AppendFormat("c{0} {1}{2}", i, c.Print(), Environment.NewLine);
                 builder.AppendFormat("d{0} {1}{2}", i, d.Print(), Environment.NewLine);
-
-
+                right = left;

                 var expansion = ExpansionPermutation(right);
                 builder.AppendFormat("Expansion permutation {0}{1}", expansion.Print(6), Environment.NewLine);
@@ -221,15 +237,16 @@
                 builder.AppendFormat("Prepermutation {0} {1}", permutation.Print(), Environment.NewLine);
                 permutation = Permutation(permutation);
                 builder.AppendFormat("Permutation {0} {1}", permutation.Print(), Environment.NewLine);
-                switchTemp = right; //para hacer el cambio de valores
-                right = permutation.Xor(left);
-                left = switchTemp;
-                builder.AppendFormat("Left{0} {1}{2}", i, left.Print(), Environment.NewLine);
-                builder.AppendFormat("Right{0} {1}{2}", i, right.Print(), Environment.NewLine);
+
+                left = permutation.Xor(right);
+
+
+                builder.AppendFormat("Left{0} {1}{2}", (i-1), left.Print(), Environment.NewLine);
+                builder.AppendFormat("Right{0} {1}{2}", (i-1), right.Print(), Environment.NewLine);
             }

-            builder.AppendFormat("Left{0} {1}{2}", " Final", left.Print(), Environment.NewLine);
-            builder.AppendFormat("Right{0} {1}{2}", " Final", right.Print(), Environment.NewLine);
+            builder.AppendFormat("Left{0} {1}{2}", " Beginning", left.Print(), Environment.NewLine);
+            builder.AppendFormat("Right{0} {1}{2}", " Beginning", right.Print(), Environment.NewLine);
             cipherbits = InverseInitialPermutation(left.Concat(right));
             builder.AppendFormat("Inverse permutation result {0}{1}", cipherbits.Print(), Environment.NewLine);
             Work = builder.ToString();


updated help text to include target/source file usage options

--- AlexanderDevelopment.ConfigDataMover.Cli/Options.cs
+++ AlexanderDevelopment.ConfigDataMover.Cli/Options.cs
@@ -31,10 +31,10 @@
         [Option('c', "configfile", Required = true, HelpText = "XML file containing job data")]
         public string ConfigFile { get; set; }

-        [Option('s', "source", Required = false, HelpText = "Simplified connection string to CRM source org - optional if connection details are specified in config file")]
+        [Option('s', "source", Required = false, HelpText = "Data source, either a simplified CRM connection string to CRM source org OR full path to source data file in the form of 'FILE=C:\\datadirectory\\datafile.json'- optional if connection details are specified in config file.")]
         public string Source { get; set; }

-        [Option('t', "target", Required = false, HelpText = "Simplified connection string to CRM target org - optional if connection details are specified in config file")]
+        [Option('t', "target", Required = false, HelpText = "Data target, either a simplified CRM connection string to CRM target org OR full path to target data file in the form of 'FILE=C:\\datadirectory\\datafile.json'- optional if connection details are specified in config file.")]
         public string Target { get; set; }

         [Option('v', "verbose", HelpText = "Print details during execution")]


Added extra members to the basic types  - SKColor  - SKPoint  - SKPointI  - SKPoint3  - SKSize  - SKSizeI  - SKRect  - SKRectI Converted fields into properties:  - SKImageInfo  - SKSurfaceProps  - SKCodecOptions

--- binding/Binding/Definitions.cs
+++ binding/Binding/Definitions.cs
@@ -82,13 +82,15 @@
 	}

 	public partial struct SKColor {
+		public static readonly SKColor Empty;
+
+		private uint color;

 		internal SKColor (uint value)
 		{
 			color = value;
 		}

-		uint color;
 		public SKColor (byte red, byte green, byte blue, byte alpha)
 		{
 			color = (uint)((alpha << 24) | (red << 16) | (green << 8) | blue);
@@ -109,6 +111,64 @@
 		public byte Green => (byte)((color >> 8) & 0xff);
 		public byte Blue => (byte)((color) & 0xff);

+		public float GetBrightness ()
+		{
+			int r = Red;
+			int g = Green;
+			int b = Blue;
+			byte minval = (byte) Math.Min (r, Math.Min (g, b));
+			byte maxval = (byte) Math.Max (r, Math.Max (g, b));
+
+			return (float)(maxval + minval) / 510;
+		}
+
+		public float GetSaturation ()
+		{
+			int r = Red;
+			int g = Green;
+			int b = Blue;
+			byte minval = (byte) Math.Min (r, Math.Min (g, b));
+			byte maxval = (byte) Math.Max (r, Math.Max (g, b));
+
+			if (maxval == minval)
+					return 0.0f;
+
+			int sum = maxval + minval;
+			if (sum > 255)
+				sum = 510 - sum;
+
+			return (float)(maxval - minval) / sum;
+		}
+
+		public float GetHue ()
+		{
+			int r = Red;
+			int g = Green;
+			int b = Blue;
+			byte minval = (byte) Math.Min (r, Math.Min (g, b));
+			byte maxval = (byte) Math.Max (r, Math.Max (g, b));
+
+			if (maxval == minval)
+					return 0.0f;
+
+			float diff = (float)(maxval - minval);
+			float rnorm = (maxval - r) / diff;
+			float gnorm = (maxval - g) / diff;
+			float bnorm = (maxval - b) / diff;
+
+			float hue = 0.0f;
+			if (r == maxval)
+				hue = 60.0f * (6.0f + bnorm - gnorm);
+			if (g == maxval)
+				hue = 60.0f * (2.0f + rnorm - bnorm);
+			if (b  == maxval)
+				hue = 60.0f * (4.0f + gnorm - rnorm);
+			if (hue > 360.0f)
+				hue = hue - 360.0f;
+
+			return hue;
+		}
+
 		public override string ToString ()
 		{
 			return string.Format (CultureInfo.InvariantCulture, "#{0:x2}{1:x2}{2:x2}{3:x2}",  Alpha, Red, Green, Blue);
@@ -136,6 +196,16 @@
 		public static explicit operator uint (SKColor color)
 		{
 			return color.color;
+		}
+
+		public static bool operator == (SKColor left, SKColor right)
+		{
+			return left.color == right.color;
+		}
+
+		public static bool operator != (SKColor left, SKColor right)
+		{
+			return !(left == right);
 		}
 	}

@@ -387,6 +457,11 @@
 		public static SKImageInfo Empty;
 		public static SKColorType PlatformColorType;

+		private int width;
+		private int height;
+		private SKColorType colorType;
+		private SKAlphaType alphaType;
+
 		static SKImageInfo ()
 		{
 #if WINDOWS_UWP
@@ -403,33 +478,48 @@
 			}
 		}

-		public int Width;
-		public int Height;
-		public SKColorType ColorType;
-		public SKAlphaType AlphaType;
+		public int Width {
+			get { return width; }
+			set { width = value; }
+		}
+
+		public int Height {
+			get { return height; }
+			set { height = value; }
+		}
+
+		public SKColorType ColorType {
+			get { return colorType; }
+			set { colorType = value; }
+		}
+
+		public SKAlphaType AlphaType {
+			get { return alphaType; }
+			set { alphaType = value; }
+		}

 		public SKImageInfo (int width, int height)
 		{
-			this.Width = width;
-			this.Height = height;
-			this.ColorType = PlatformColorType;
-			this.AlphaType = SKAlphaType.Premul;
+			this.width = width;
+			this.height = height;
+			this.colorType = PlatformColorType;
+			this.alphaType = SKAlphaType.Premul;
 		}

 		public SKImageInfo (int width, int height, SKColorType colorType)
 		{
-			this.Width = width;
-			this.Height = height;
-			this.ColorType = colorType;
-			this.AlphaType = SKAlphaType.Premul;
+			this.width = width;
+			this.height = height;
+			this.colorType = colorType;
+			this.alphaType = SKAlphaType.Premul;
 		}

 		public SKImageInfo (int width, int height, SKColorType colorType, SKAlphaType alphaType)
 		{
-			this.Width = width;
-			this.Height = height;
-			this.ColorType = colorType;
-			this.AlphaType = alphaType;
+			this.width = width;
+			this.height = height;
+			this.colorType = colorType;
+			this.alphaType = alphaType;
 		}

 		public int BytesPerPixel {
@@ -481,7 +571,12 @@

 	[StructLayout(LayoutKind.Sequential)]
 	public struct SKSurfaceProps {
-		public SKPixelGeometry PixelGeometry;
+		private SKPixelGeometry pixelGeometry;
+
+		public SKPixelGeometry PixelGeometry {
+			get { return pixelGeometry; }
+			set { pixelGeometry = value; }
+		}
 	}

 	public enum SKZeroInitialized {
@@ -492,51 +587,47 @@
 	[StructLayout(LayoutKind.Sequential)]
 	public struct SKCodecOptions {
 		public static readonly SKCodecOptions Default;
+
+		private SKZeroInitialized zeroInitialized;
+		private SKRectI subset;
+		private bool hasSubset;
+
 		static SKCodecOptions ()
 		{
 			Default = new SKCodecOptions (SKZeroInitialized.No);
 		}
 		public SKCodecOptions (SKZeroInitialized zeroInitialized) {
-			ZeroInitialized = zeroInitialized;
-			Subset = SKRectI.Empty;
-			HasSubset = false;
+			this.zeroInitialized = zeroInitialized;
+			this.subset = SKRectI.Empty;
+			this.hasSubset = false;
 		}
 		public SKCodecOptions (SKZeroInitialized zeroInitialized, SKRectI subset) {
-			ZeroInitialized = zeroInitialized;
-			Subset = subset;
-			HasSubset = true;
-		}
-		public SKZeroInitialized ZeroInitialized;
-		public SKRectI Subset;
-		public bool HasSubset;
+			this.zeroInitialized = zeroInitialized;
+			this.subset = subset;
+			this.hasSubset = true;
+		}
+		public SKZeroInitialized ZeroInitialized{
+			get { return zeroInitialized; }
+			set { zeroInitialized = value; }
+		}
+
+		public SKRectI Subset{
+			get { return subset; }
+			set { subset = value; }
+		}
+
+		public bool HasSubset{
+			get { return hasSubset; }
+			set { hasSubset = value; }
+		}
 	}

 	[StructLayout(LayoutKind.Sequential)]
 	public struct SKPoint {
 		private float x, y;
-		// -----------------------
-		// Public Shared Members
-		// -----------------------
-
-		/// <summary>
-		///	Empty Shared Field
-		/// </summary>
-		///
-		/// <remarks>
-		///	An uninitialized SKPoint Structure.
-		/// </remarks>
-
+
 		public static readonly SKPoint Empty;

-		/// <summary>
-		///	Addition Operator
-		/// </summary>
-		///
-		/// <remarks>
-		///	Translates a SKPoint using the Width and Height
-		///	properties of the given SKSize.
-		/// </remarks>
-
 		public static SKPoint operator + (SKPoint pt, SKSizeI sz)
 		{
 			return new SKPoint (pt.X + sz.Width, pt.Y + sz.Height);
@@ -546,45 +637,25 @@
 			return new SKPoint (pt.X + sz.Width, pt.Y + sz.Height);
 		}

-		/// <summary>
-		///	Equality Operator
-		/// </summary>
-		///
-		/// <remarks>
-		///	Compares two SKPoint objects. The return value is
-		///	based on the equivalence of the X and Y properties
-		///	of the two points.
-		/// </remarks>
-
+		public static SKPoint operator + (SKPoint pt, SKPointI sz)
+		{
+			return new SKPoint (pt.X + sz.X, pt.Y + sz.Y);
+		}
+		public static SKPoint operator + (SKPoint pt, SKPoint sz)
+		{
+			return new SKPoint (pt.X + sz.X, pt.Y + sz.Y);
+		}
+
 		public static bool operator == (SKPoint left, SKPoint right)
 		{
 			return ((left.X == right.X) && (left.Y == right.Y));
 		}

-		/// <summary>
-		///	Inequality Operator
-		/// </summary>
-		///
-		/// <remarks>
-		///	Compares two SKPoint objects. The return value is
-		///	based on the equivalence of the X and Y properties
-		///	of the two points.
-		/// </remarks>
-
 		public static bool operator != (SKPoint left, SKPoint right)
 		{
-			return ((left.X != right.X) || (left.Y != right.Y));
-		}
-
-		/// <summary>
-		///	Subtraction Operator
-		/// </summary>
-		///
-		/// <remarks>
-		///	Translates a SKPoint using the negation of the Width
-		///	and Height properties of the given SKSize.
-		/// </remarks>
-
+			return !(left == right);
+		}
+
 		public static SKPoint operator - (SKPoint pt, SKSizeI sz)
 		{
 			return new SKPoint (pt.X - sz.Width, pt.Y - sz.Height);
@@ -594,17 +665,14 @@
 			return new SKPoint (pt.X - sz.Width, pt.Y - sz.Height);
 		}

-		// -----------------------
-		// Public Constructor
-		// -----------------------
-
-		/// <summary>
-		///	SKPoint Constructor
-		/// </summary>
-		///
-		/// <remarks>
-		///	Creates a SKPoint from a specified x,y coordinate pair.
-		/// </remarks>
+		public static SKPoint operator - (SKPoint pt, SKPointI sz)
+		{
+			return new SKPoint (pt.X - sz.X, pt.Y - sz.Y);
+		}
+		public static SKPoint operator - (SKPoint pt, SKPoint sz)
+		{
+			return new SKPoint (pt.X - sz.X, pt.Y - sz.Y);
+		}

 		public SKPoint (float x, float y)
 		{
@@ -612,32 +680,12 @@
 			this.y = y;
 		}

-		// -----------------------
-		// Public Instance Members
-		// -----------------------
-
-		/// <summary>
-		///	IsEmpty Property
-		/// </summary>
-		///
-		/// <remarks>
-		///	Indicates if both X and Y are zero.
-		/// </remarks>
-
 		public bool IsEmpty {
 			get {
 				return ((x == 0.0) && (y == 0.0));
 			}
 		}

-		/// <summary>
-		///	X Property
-		/// </summary>
-		///
-		/// <remarks>
-		///	The X coordinate of the SKPoint.
-		/// </remarks>
-
 		public float X {
 			get {
 				return x;
@@ -647,14 +695,6 @@
 			}
 		}

-		/// <summary>
-		///	Y Property
-		/// </summary>
-		///
-		/// <remarks>
-		///	The Y coordinate of the SKPoint.
-		/// </remarks>
-
 		public float Y {
 			get {
 				return y;
@@ -664,14 +704,6 @@
 			}
 		}

-		/// <summary>
-		///	Equals Method
-		/// </summary>
-		///
-		/// <remarks>
-		///	Checks equivalence of this SKPoint and another object.
-		/// </remarks>
-
 		public override bool Equals (object obj)
 		{
 			if (!(obj is SKPoint))
@@ -680,82 +712,36 @@
 			return (this == (SKPoint) obj);
 		}

-		/// <summary>
-		///	GetHashCode Method
-		/// </summary>
-		///
-		/// <remarks>
-		///	Calculates a hashing value.
-		/// </remarks>
-
 		public override int GetHashCode ()
 		{
 			return (int) x ^ (int) y;
 		}

-		/// <summary>
-		///	ToString Method
-		/// </summary>
-		///
-		/// <remarks>
-		///	Formats the SKPoint as a string in coordinate notation.
-		/// </remarks>
-
 		public override string ToString ()
 		{
-			return String.Format ("{{X={0}, Y={1}}}", x.ToString (CultureInfo.CurrentCulture),
+			return String.Format (
+				"{{X={0}, Y={1}}}",
+				x.ToString (CultureInfo.CurrentCulture),
 				y.ToString (CultureInfo.CurrentCulture));
 		}

-		public static SKPoint Add (SKPoint pt, SKSizeI sz)
-		{
-			return new SKPoint (pt.X + sz.Width, pt.Y + sz.Height);
-		}
-
-		public static SKPoint Add (SKPoint pt, SKSize sz)
-		{
-			return new SKPoint (pt.X + sz.Width, pt.Y + sz.Height);
-		}
-
-		public static SKPoint Subtract (SKPoint pt, SKSizeI sz)
-		{
-			return new SKPoint (pt.X - sz.Width, pt.Y - sz.Height);
-		}
-
-		public static SKPoint Subtract (SKPoint pt, SKSize sz)
-		{
-			return new SKPoint (pt.X - sz.Width, pt.Y - sz.Height);
-		}
+		public static SKPoint Add (SKPoint pt, SKSizeI sz) => pt + sz;
+		public static SKPoint Add (SKPoint pt, SKSize sz) => pt + sz;
+		public static SKPoint Add (SKPoint pt, SKPointI sz) => pt + sz;
+		public static SKPoint Add (SKPoint pt, SKPoint sz) => pt + sz;
+
+		public static SKPoint Subtract (SKPoint pt, SKSizeI sz) => pt - sz;
+		public static SKPoint Subtract (SKPoint pt, SKSize sz) => pt - sz;
+		public static SKPoint Subtract (SKPoint pt, SKPointI sz) => pt - sz;
+		public static SKPoint Subtract (SKPoint pt, SKPoint sz) => pt - sz;
 	}

 	[StructLayout(LayoutKind.Sequential)]
 	public struct SKPointI {
-		// Private x and y coordinate fields.
 		private int x, y;

-		// -----------------------
-		// Public Shared Members
-		// -----------------------
-
-		/// <summary>
-		///	Empty Shared Field
-		/// </summary>
-		///
-		/// <remarks>
-		///	An uninitialized Point Structure.
-		/// </remarks>
-
 		public static readonly SKPointI Empty;

-		/// <summary>
-		///	Ceiling Shared Method
-		/// </summary>
-		///
-		/// <remarks>
-		///	Produces a Point structure from a PointF structure by
-		///	taking the ceiling of the X and Y properties.
-		/// </remarks>
-
 		public static SKPointI Ceiling (SKPoint value)
 		{
 			int x, y;
@@ -767,15 +753,6 @@
 			return new SKPointI (x, y);
 		}

-		/// <summary>
-		///	Round Shared Method
-		/// </summary>
-		///
-		/// <remarks>
-		///	Produces a Point structure from a PointF structure by
-		///	rounding the X and Y properties.
-		/// </remarks>
-
 		public static SKPointI Round (SKPoint value)
 		{
 			int x, y;
@@ -787,17 +764,6 @@
 			return new SKPointI (x, y);
 		}

-		/// <summary>
-		///	Truncate Shared Method
-		/// </summary>
-		///
-		/// <remarks>
-		///	Produces a Point structure from a PointF structure by
-		///	truncating the X and Y properties.
-		/// </remarks>
-
-		// LAMESPEC: Should this be floor, or a pure cast to int?
-
 		public static SKPointI Truncate (SKPoint value)
 		{
 			int x, y;
@@ -809,151 +775,64 @@
 			return new SKPointI (x, y);
 		}

-		/// <summary>
-		///	Addition Operator
-		/// </summary>
-		///
-		/// <remarks>
-		///	Translates a Point using the Width and Height
-		///	properties of the given <typeref>Size</typeref>.
-		/// </remarks>
-
 		public static SKPointI operator + (SKPointI pt, SKSizeI sz)
 		{
 			return new SKPointI (pt.X + sz.Width, pt.Y + sz.Height);
 		}

-		/// <summary>
-		///	Equality Operator
-		/// </summary>
-		///
-		/// <remarks>
-		///	Compares two Point objects. The return value is
-		///	based on the equivalence of the X and Y properties
-		///	of the two points.
-		/// </remarks>
-
+		public static SKPointI operator + (SKPointI pt, SKPointI sz)
+		{
+			return new SKPointI (pt.X + sz.X, pt.Y + sz.Y);
+		}
+
 		public static bool operator == (SKPointI left, SKPointI right)
 		{
 			return ((left.X == right.X) && (left.Y == right.Y));
 		}

-		/// <summary>
-		///	Inequality Operator
-		/// </summary>
-		///
-		/// <remarks>
-		///	Compares two Point objects. The return value is
-		///	based on the equivalence of the X and Y properties
-		///	of the two points.
-		/// </remarks>
-
 		public static bool operator != (SKPointI left, SKPointI right)
 		{
-			return ((left.X != right.X) || (left.Y != right.Y));
-		}
-
-		/// <summary>
-		///	Subtraction Operator
-		/// </summary>
-		///
-		/// <remarks>
-		///	Translates a Point using the negation of the Width
-		///	and Height properties of the given Size.
-		/// </remarks>
-
+			return !(left == right);
+		}
+
 		public static SKPointI operator - (SKPointI pt, SKSizeI sz)
 		{
 			return new SKPointI (pt.X - sz.Width, pt.Y - sz.Height);
 		}

-		/// <summary>
-		///	Point to Size Conversion
-		/// </summary>
-		///
-		/// <remarks>
-		///	Returns a Size based on the Coordinates of a given
-		///	Point. Requires explicit cast.
-		/// </remarks>
-
+		public static SKPointI operator - (SKPointI pt, SKPointI sz)
+		{
+			return new SKPointI (pt.X - sz.X, pt.Y - sz.Y);
+		}
+
 		public static explicit operator SKSizeI (SKPointI p)
 		{
 			return new SKSizeI (p.X, p.Y);
 		}

-		/// <summary>
-		///	Point to PointF Conversion
-		/// </summary>
-		///
-		/// <remarks>
-		///	Creates a PointF based on the coordinates of a given
-		///	Point. No explicit cast is required.
-		/// </remarks>
-
 		public static implicit operator SKPoint (SKPointI p)
 		{
 			return new SKPoint (p.X, p.Y);
 		}

-
-		// -----------------------
-		// Public Constructors
-		// -----------------------
-
-		/// <summary>
-		///	Point Constructor
-		/// </summary>
-		///
-		/// <remarks>
-		///	Creates a Point from a Size value.
-		/// </remarks>
-
 		public SKPointI (SKSizeI sz)
 		{
 			x = sz.Width;
 			y = sz.Height;
 		}

-		/// <summary>
-		///	Point Constructor
-		/// </summary>
-		///
-		/// <remarks>
-		///	Creates a Point from a specified x,y coordinate pair.
-		/// </remarks>
-
 		public SKPointI (int x, int y)
 		{
 			this.x = x;
 			this.y = y;
 		}

-		// -----------------------
-		// Public Instance Members
-		// -----------------------
-
-		/// <summary>
-		///	IsEmpty Property
-		/// </summary>
-		///
-		/// <remarks>
-		///	Indicates if both X and Y are zero.
-		/// </remarks>
-
 		public bool IsEmpty {
 			get {
 				return ((x == 0) && (y == 0));
 			}
 		}

-		/// <summary>
-		///	X Property
-		/// </summary>
-		///
-		/// <remarks>
-		///	The X coordinate of the Point.
-		/// </remarks>
-
 		public int X {
 			get {
 				return x;
@@ -963,14 +842,6 @@
 			}
 		}

-		/// <summary>
-		///	Y Property
-		/// </summary>
-		///
-		/// <remarks>
-		///	The Y coordinate of the Point.
-		/// </remarks>
-
 		public int Y {
 			get {
 				return y;
@@ -980,14 +851,6 @@
 			}
 		}

-		/// <summary>
-		///	Equals Method
-		/// </summary>
-		///
-		/// <remarks>
-		///	Checks equivalence of this Point and another object.
-		/// </remarks>
-
 		public override bool Equals (object obj)
 		{
 			if (!(obj is SKPointI))
@@ -996,60 +859,35 @@
 			return (this == (SKPointI) obj);
 		}

-		/// <summary>
-		///	GetHashCode Method
-		/// </summary>
-		///
-		/// <remarks>
-		///	Calculates a hashing value.
-		/// </remarks>
-
 		public override int GetHashCode ()
 		{
 			return x^y;
 		}
-
-		/// <summary>
-		///	Offset Method
-		/// </summary>
-		///
-		/// <remarks>
-		///	Moves the Point a specified distance.
-		/// </remarks>

 		public void Offset (int dx, int dy)
 		{
 			x += dx;
 			y += dy;
 		}
-
-		/// <summary>
-		///	ToString Method
-		/// </summary>
-		///
-		/// <remarks>
-		///	Formats the Point as a string in coordinate notation.
-		/// </remarks>
-
+
 		public override string ToString ()
 		{
-			return string.Format ("{{X={0},Y={1}}}", x.ToString (CultureInfo.InvariantCulture),
+			return string.Format (
+				"{{X={0},Y={1}}}",
+				x.ToString (CultureInfo.InvariantCulture),
 				y.ToString (CultureInfo.InvariantCulture));
 		}
-		public static SKPointI Add (SKPointI pt, SKSizeI sz)
-		{
-			return new SKPointI (pt.X + sz.Width, pt.Y + sz.Height);
-		}

 		public void Offset (SKPointI p)
 		{
 			Offset (p.X, p.Y);
 		}

-		public static SKPointI Subtract (SKPointI pt, SKSizeI sz)
-		{
-			return new SKPointI (pt.X - sz.Width, pt.Y - sz.Height);
-		}
+		public static SKPointI Add (SKPointI pt, SKSizeI sz) => pt + sz;
+		public static SKPointI Add (SKPointI pt, SKPointI sz) => pt + sz;
+
+		public static SKPointI Subtract (SKPointI pt, SKSizeI sz) => pt - sz;
+		public static SKPointI Subtract (SKPointI pt, SKPointI sz) => pt - sz;
 	}

 	[StructLayout(LayoutKind.Sequential)]
@@ -1085,7 +923,6 @@
 			}
 		}

-
 		public SKPoint3(float x, float y, float z)
 		{
 			this.x = x;
@@ -1093,6 +930,16 @@
 			this.z = z;
 		}

+		public static SKPoint3 operator + (SKPoint3 pt, SKPoint3 sz)
+		{
+			return new SKPoint3 (pt.X + sz.X, pt.Y + sz.Y, pt.Z + sz.Z);
+		}
+
+		public static SKPoint3 operator - (SKPoint3 pt, SKPoint3 sz)
+		{
+			return new SKPoint3 (pt.X - sz.X, pt.Y - sz.Y, pt.Z - sz.Z);
+		}
+
 		public static bool operator == (SKPoint3 left, SKPoint3 right)
 		{
 			return ((left.x == right.x) && (left.y == right.y) && (left.z == right.z));
@@ -1100,7 +947,7 @@

 		public static bool operator != (SKPoint3 left, SKPoint3 right)
 		{
-			return ((left.x != right.x) || (left.y != right.y) || (left.z != right.z));
+			return !(left == right);
 		}

 		public bool IsEmpty {
@@ -1130,45 +977,446 @@
 					      z.ToString (CultureInfo.CurrentCulture)
 				);
 		}
+
+		public static SKPoint3 Add (SKPoint3 pt, SKPoint3 sz) => pt + sz;
+
+		public static SKPoint3 Subtract (SKPoint3 pt, SKPoint3 sz) => pt - sz;
 	}

 	[StructLayout(LayoutKind.Sequential)]
 	public struct SKSize
 	{
-		public float Width, Height;
-		public SKSize(float width, float height)
-		{
-			Width = width;
-			Height = height;
-		}
+		private float width, height;
+
+		public static readonly SKSize Empty;
+
+		public SKSize (float width, float height)
+		{
+			this.width = width;
+			this.height = height;
+		}
+
+		public SKSize (SKPoint pt)
+		{
+			this.width = pt.X;
+			this.height = pt.Y;
+		}
+
+		public bool IsEmpty => (width == 0) && (height == 0);
+
+		public float Width {
+			get { return width; }
+			set { width = value; }
+		}
+
+		public float Height {
+			get { return height; }
+			set { height = value; }
+		}
+
+		public SKPoint ToPoint ()
+		{
+			return new SKPoint (width, height);
+		}
+
+		public SKSizeI ToSizeI ()
+		{
+			int w, h;
+			checked {
+				w = (int) width;
+				h = (int) height;
+			}
+
+			return new SKSizeI (w, h);
+		}
+
+		public static SKSize operator + (SKSize sz1, SKSize sz2)
+		{
+			return new SKSize (sz1.Width + sz2.Width, sz1.Height + sz2.Height);
+		}
+
+		public static SKSize operator - (SKSize sz1, SKSize sz2)
+		{
+			return new SKSize (sz1.Width - sz2.Width, sz1.Height - sz2.Height);
+		}
+
+		public static bool operator == (SKSize sz1, SKSize sz2)
+		{
+			return ((sz1.Width == sz2.Width) && (sz1.Height == sz2.Height));
+		}
+
+		public static bool operator != (SKSize sz1, SKSize sz2)
+		{
+			return !(sz1 == sz2);
+		}
+
+		public static explicit operator SKPoint (SKSize size)
+		{
+			return new SKPoint (size.Width, size.Height);
+		}
+
+		public static implicit operator SKSize (SKSizeI size)
+		{
+			return new SKSize (size.Width, size.Height);
+		}
+
+		public override bool Equals (object obj)
+		{
+			if (!(obj is SKSize))
+				return false;
+
+			return (this == (SKSize) obj);
+		}
+
+		public override int GetHashCode ()
+		{
+			return (int) width ^ (int) height;
+		}
+
+		public override string ToString ()
+		{
+			return string.Format (
+				"{{Width={0}, Height={1}}}",
+				width.ToString (CultureInfo.CurrentCulture),
+				height.ToString (CultureInfo.CurrentCulture));
+		}
+
+		public static SKSize Add (SKSize sz1, SKSize sz2) => sz1 + sz2;
+
+		public static SKSize Subtract (SKSize sz1, SKSize sz2) => sz1 - sz2;
 	}

 	[StructLayout(LayoutKind.Sequential)]
 	public struct SKSizeI
 	{
-		public int Width, Height;
-		public SKSizeI(int width, int height)
-		{
-			Width = width;
-			Height = height;
-		}
+		private int width, height;
+
+		public static readonly SKSizeI Empty;
+
+		public SKSizeI (int width, int height)
+		{
+			this.width = width;
+			this.height = height;
+		}
+
+		public SKSizeI (SKPointI pt)
+		{
+			this.width = pt.X;
+			this.height = pt.Y;
+		}
+
+		public bool IsEmpty => (width == 0) && (height == 0);
+
+		public int Width {
+			get { return width; }
+			set { width = value; }
+		}
+
+		public int Height {
+			get { return height; }
+			set { height = value; }
+		}
+
+		public SKPointI ToPointI ()
+		{
+			return new SKPointI (width, height);
+		}
+
+		public static SKSizeI operator + (SKSizeI sz1, SKSizeI sz2)
+		{
+			return new SKSizeI (sz1.Width + sz2.Width, sz1.Height + sz2.Height);
+		}
+
+		public static SKSizeI operator - (SKSizeI sz1, SKSizeI sz2)
+		{
+			return new SKSizeI (sz1.Width - sz2.Width, sz1.Height - sz2.Height);
+		}
+
+		public static bool operator == (SKSizeI sz1, SKSizeI sz2)
+		{
+			return ((sz1.Width == sz2.Width) && (sz1.Height == sz2.Height));
+		}
+
+		public static bool operator != (SKSizeI sz1, SKSizeI sz2)
+		{
+			return !(sz1 == sz2);
+		}
+
+		public static explicit operator SKPointI (SKSizeI size)
+		{
+			return new SKPointI (size.Width, size.Height);
+		}
+
+		public override bool Equals (object obj)
+		{
+			if (!(obj is SKSizeI))
+				return false;
+
+			return (this == (SKSizeI) obj);
+		}
+
+		public override int GetHashCode ()
+		{
+			return (int) width ^ (int) height;
+		}
+
+		public override string ToString ()
+		{
+			return string.Format (
+				"{{Width={0}, Height={1}}}",
+				width.ToString (CultureInfo.CurrentCulture),
+				height.ToString (CultureInfo.CurrentCulture));
+		}
+
+		public static SKSizeI Add (SKSizeI sz1, SKSizeI sz2) => sz1 + sz2;
+
+		public static SKSizeI Subtract (SKSizeI sz1, SKSizeI sz2) => sz1 - sz2;
 	}

 	[StructLayout(LayoutKind.Sequential)]
 	public struct SKRectI {
 		public static readonly SKRectI Empty;
-		public int Left, Top, Right, Bottom;
+
+		private int left, top, right, bottom;
+
 		public SKRectI (int left, int top, int right, int bottom)
 		{
-			Left = left;
-			Right = right;
-			Top = top;
-			Bottom = bottom;
+			this.left = left;
+			this.right = right;
+			this.top = top;
+			this.bottom = bottom;
+		}
+
+		public int Left {
+			get { return left; }
+			set { left = value; }
+		}
+
+		public int Top {
+			get { return top; }
+			set { top = value; }
+		}
+
+		public int Right {
+			get { return right; }
+			set { right = value; }
+		}
+
+		public int Bottom {
+			get { return bottom; }
+			set { bottom = value; }
+		}
+
+		public int Width => right - left;
+
+		public int Height => bottom - top;
+
+		public bool IsEmpty => this == Empty;
+
+		public SKSizeI Size {
+			get { return new SKSizeI (Width, Height); }
+			set {
+				right = left + value.Width;
+				bottom = top + value.Height;
+			}
+		}
+
+		public SKPointI Location {
+			get { return new SKPointI (left, top); }
+			set {
+				left = value.X;
+				top = value.Y;
+			}
+		}
+
+		public static SKRectI Ceiling (SKRect value)
+		{
+			int x, y, r, b;
+			checked {
+				x = (int) Math.Ceiling (value.Left);
+				y = (int) Math.Ceiling (value.Top);
+				r = (int) Math.Ceiling (value.Right);
+				b = (int) Math.Ceiling (value.Bottom);
+			}
+
+			return new SKRectI (x, y, r, b);
+		}
+
+		public static SKRectI Inflate (SKRectI rect, int x, int y)
+		{
+			SKRectI r = new SKRectI (rect.left, rect.top, rect.right, rect.bottom);
+			r.Inflate (x, y);
+			return r;
+		}
+
+		public void Inflate (SKSizeI size)
+		{
+			Inflate (size.Width, size.Height);
+		}
+
+		public void Inflate (int width, int height)
+		{
+			left -= width;
+			top -= height;
+			right += width;
+			bottom += height;
+		}
+
+		public static SKRectI Intersect (SKRectI a, SKRectI b)
+		{
+			if (!a.IntersectsWithInclusive (b))
+				return Empty;
+
+			return new SKRectI (
+				Math.Max (a.left, b.left),
+				Math.Max (a.top, b.top),
+				Math.Min (a.right, b.right),
+				Math.Min (a.bottom, b.bottom));
+		}
+
+		public void Intersect (SKRectI rect)
+		{
+			this = SKRectI.Intersect (this, rect);
+		}
+
+		public static SKRectI Round (SKRect value)
+		{
+			int x, y, r, b;
+			checked {
+				x = (int) Math.Round (value.Left);
+				y = (int) Math.Round (value.Top);
+				r = (int) Math.Round (value.Right);
+				b = (int) Math.Round (value.Bottom);
+			}
+
+			return new SKRectI (x, y, r, b);
+		}
+
+		public static SKRectI Truncate (SKRect value)
+		{
+			int x, y, r, b;
+			checked {
+				x = (int) value.Left;
+				y = (int) value.Top;
+				r = (int) value.Right;
+				b = (int) value.Bottom;
+			}
+
+			return new SKRectI (x, y, r, b);
+		}
+
+		public static SKRectI Union (SKRectI a, SKRectI b)
+		{
+			return new SKRectI (
+				Math.Min (a.Left, b.Left),
+				Math.Min (a.Top, b.Top),
+				Math.Max (a.Right, b.Right),
+				Math.Max (a.Bottom, b.Bottom));
+		}
+
+		public void Union (SKRectI rect)
+		{
+			this = SKRectI.Union (this, rect);
+		}
+
+		public bool Contains (int x, int y)
+		{
+			return
+				(x >= left) && (x < right) &&
+				(y >= top) && (y < bottom);
+		}
+
+		public bool Contains (SKPointI pt)
+		{
+			return Contains (pt.X, pt.Y);
+		}
+
+		public bool Contains (SKRectI rect)
+		{
+			return
+				(left <= rect.left) && (right >= rect.right) &&
+				(top <= rect.top) && (bottom >= rect.bottom);
+		}
+
+		public override bool Equals (object obj)
+		{
+			if (!(obj is SKRectI))
+				return false;
+
+			return (this == (SKRectI) obj);
+		}
+
+		public override int GetHashCode ()
+		{
+			return unchecked((int)(
+				(((UInt32)Left)) ^
+				(((UInt32)Top << 13) | ((UInt32)Top >> 19)) ^
+				(((UInt32)Width << 26) | ((UInt32)Width >>  6)) ^
+				(((UInt32)Height <<  7) | ((UInt32)Height >> 25))));
+		}
+
+		public bool IntersectsWith (SKRectI rect)
+		{
+			return
+				!((left >= rect.right) || (right <= rect.left) ||
+				  (top >= rect.bottom) || (bottom <= rect.top));
+		}
+
+		private bool IntersectsWithInclusive (SKRectI r)
+		{
+			return
+				!((left > r.right) || (right < r.left) ||
+				  (top > r.bottom) || (bottom < r.top));
+		}
+
+		public void Offset (int x, int y)
+		{
+			left += x;
+			top += y;
+			right += x;
+			bottom += y;
+		}
+
+		public void Offset (SKPointI pos)
+		{
+			Offset (pos.X, pos.Y);
+		}
+
+		public override string ToString ()
+		{
+			return String.Format (
+				"{{Left={0},Top={1},Width={2},Height={3}}}",
+				Left.ToString (CultureInfo.CurrentCulture),
+				Top.ToString (CultureInfo.CurrentCulture),
+				Width.ToString (CultureInfo.CurrentCulture),
+				Height.ToString (CultureInfo.CurrentCulture));
+		}
+
+		public static bool operator == (SKRectI left, SKRectI right)
+		{
+			return
+				(left.left == right.left) && (left.top == right.top) &&
+				(left.right == right.right) && (left.bottom == right.bottom);
+		}
+
+		public static bool operator != (SKRectI left, SKRectI right)
+		{
+			return !(left == right);
+		}
+
+		public static SKRectI Create (SKSizeI size)
+		{
+			return SKRectI.Create (SKPointI.Empty.X, SKPointI.Empty.Y, size.Width, size.Height);
+		}
+
+		public static SKRectI Create (SKPointI location, SKSizeI size)
+		{
+			return SKRectI.Create (location.X, location.Y, size.Width, size.Height);
 		}

 		public static SKRectI Create (int width, int height)
 		{
-			return new SKRectI (0, 0, width, height);
+			return new SKRectI (SKPointI.Empty.X, SKPointI.Empty.X, width, height);
 		}

 		public static SKRectI Create (int x, int y, int width, int height)
@@ -1179,18 +1427,210 @@

 	[StructLayout(LayoutKind.Sequential)]
 	public struct SKRect {
-		public float Left, Top, Right, Bottom;
+		public static readonly SKRect Empty;
+
+		private float left, top, right, bottom;
+
 		public SKRect (float left, float top, float right, float bottom)
 		{
-			Left = left;
-			Right = right;
-			Top = top;
-			Bottom = bottom;
+			this.left = left;
+			this.right = right;
+			this.top = top;
+			this.bottom = bottom;
+		}
+
+		public float Left {
+			get { return left; }
+			set { left = value; }
+		}
+
+		public float Top {
+			get { return top; }
+			set { top = value; }
+		}
+
+		public float Right {
+			get { return right; }
+			set { right = value; }
+		}
+
+		public float Bottom {
+			get { return bottom; }
+			set { bottom = value; }
+		}
+
+		public float Width => right - left;
+
+		public float Height => bottom - top;
+
+		public bool IsEmpty => this == Empty;
+
+		public SKSize Size {
+			get { return new SKSize (Width, Height); }
+			set {
+				right = left + value.Width;
+				bottom = top + value.Height;
+			}
+		}
+
+		public SKPoint Location {
+			get { return new SKPoint (left, top); }
+			set {
+				left = value.X;
+				top = value.Y;
+			}
+		}
+
+		public static SKRect Inflate (SKRect rect, float x, float y)
+		{
+			var r = new SKRect (rect.left, rect.top, rect.right, rect.bottom);
+			r.Inflate (x, y);
+			return r;
+		}
+
+		public void Inflate (SKSize size)
+		{
+			Inflate (size.Width, size.Height);
+		}
+
+		public void Inflate (float x, float y)
+		{
+			left -= x;
+			top -= y;
+			right += x;
+			bottom += y;
+		}
+
+		public static SKRect Intersect (SKRect a, SKRect b)
+		{
+			if (!a.IntersectsWithInclusive (b)) {
+				return Empty;
+			}
+			return new SKRect (
+				Math.Max (a.left, b.left),
+				Math.Max (a.top, b.top),
+				Math.Min (a.right, b.right),
+				Math.Min (a.bottom, b.bottom));
+		}
+
+		public void Intersect (SKRect rect)
+		{
+			this = SKRect.Intersect (this, rect);
+		}
+
+		public static SKRect Union (SKRect a, SKRect b)
+		{
+			return new SKRect (
+				Math.Min (a.left, b.left),
+				Math.Min (a.top, b.top),
+				Math.Max (a.right, b.right),
+				Math.Max (a.bottom, b.bottom));
+		}
+
+		public void Union (SKRect rect)
+		{
+			this = SKRect.Union (this, rect);
+		}
+
+		public static bool operator == (SKRect left, SKRect right)
+		{
+			return
+				(left.left == right.left) && (left.top == right.top) &&
+				(left.right == right.right) && (left.bottom == right.bottom);
+		}
+
+		public static bool operator != (SKRect left, SKRect right)
+		{
+			return !(left == right);
+		}
+
+		public static implicit operator SKRect (SKRectI r)
+		{
+			return new SKRect (r.Left, r.Top, r.Right, r.Bottom);
+		}
+
+		public bool Contains (float x, float y)
+		{
+			return (x >= left) && (x < right) && (y >= top) && (y < bottom);
+		}
+
+		public bool Contains (SKPoint pt)
+		{
+			return Contains (pt.X, pt.Y);
+		}
+
+		public bool Contains (SKRect rect)
+		{
+			return
+				(left <= rect.left) && (right >= rect.right) &&
+				(top <= rect.top) && (bottom >= rect.bottom);
+		}
+
+		public override bool Equals (object obj)
+		{
+			if (!(obj is SKRect))
+				return false;
+
+			return this == (SKRect) obj;
+		}
+
+		public override int GetHashCode ()
+		{
+			return unchecked((int)(
+				(((UInt32)Left)) ^
+				(((UInt32)Top << 13) | ((UInt32)Top >> 19)) ^
+				(((UInt32)Width << 26) | ((UInt32)Width >>  6)) ^
+				(((UInt32)Height <<  7) | ((UInt32)Height >> 25))));
+		}
+
+		public bool IntersectsWith (SKRect rect)
+		{
+			return !((left >= rect.right) || (right <= rect.left) ||
+					(top >= rect.bottom) || (bottom <= rect.top));
+		}
+
+		public bool IntersectsWithInclusive (SKRect rect)
+		{
+			return !((left > rect.right) || (right < rect.left) ||
+					 (top > rect.bottom) || (bottom < rect.top));
+		}
+
+		public void Offset (float x, float y)
+		{
+			left += x;
+			top += y;
+			right += x;
+			bottom += y;
+		}
+
+		public void Offset (SKPoint pos)
+		{
+			Offset (pos.X, pos.Y);
+		}
+
+		public override string ToString ()
+		{
+			return String.Format (
+				"{{Left={0},Top={1},Width={2},Height={3}}}",
+				Left.ToString (CultureInfo.CurrentCulture),
+				Top.ToString (CultureInfo.CurrentCulture),
+				Width.ToString (CultureInfo.CurrentCulture),
+				Height.ToString (CultureInfo.CurrentCulture));
+		}
+
+		public static SKRect Create (SKPoint location, SKSize size)
+		{
+			return SKRect.Create (location.X, location.Y, size.Width, size.Height);
+		}
+
+		public static SKRect Create (SKSize size)
+		{
+			return SKRect.Create (SKPoint.Empty, size);
 		}

 		public static SKRect Create (float width, float height)
 		{
-			return new SKRect (0, 0, width, height);
+			return new SKRect (SKPoint.Empty.X, SKPoint.Empty.Y, width, height);
 		}

 		public static SKRect Create (float x, float y, float width, float height)


Fixed invalid action in SendMessage

Fixed invalid action in SendMessage

--- Altairis.Fakturoid.Client/FakturoidInvoicesProxy.cs
+++ Altairis.Fakturoid.Client/FakturoidInvoicesProxy.cs
@@ -246,10 +246,10 @@
                     eventName = "deliver";
                     break;
                 case InvoiceMessageType.PaymentReminderMessage:
+                    eventName = "deliver_reminder";
+                    break;
+                default:
                     eventName = "mark_as_sent";
-                    break;
-                default:
-                    eventName = "deliver_reminder";
                     break;
             }


Uncaught exception handler for droid

Uncaught exception handler for droid

--- Ao3TrackReader/Ao3TrackReader.Droid/MainActivity.cs
+++ Ao3TrackReader/Ao3TrackReader.Droid/MainActivity.cs
@@ -26,11 +26,12 @@
 using Android.OS;
 using Ao3TrackReader.Controls;
 using Xamarin.Forms.Platform.Android;
+using Java.Lang;

 namespace Ao3TrackReader.Droid
 {
     [Activity(Label = "Ao3TrackReader", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
-    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
+    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity, Java.Lang.Thread.IUncaughtExceptionHandler
     {
         protected override void OnCreate(Bundle bundle)
         {
@@ -44,6 +45,7 @@
                     SetTheme(Ao3TrackReader.Droid.Resource.Style.DarkTheme);
                     break;
             }
+            Java.Lang.Thread.DefaultUncaughtExceptionHandler = this;
             base.OnCreate(bundle);
             global::Xamarin.Forms.Forms.Init(this, bundle);

@@ -195,6 +197,11 @@

             return res;
         }
+
+        void Thread.IUncaughtExceptionHandler.UncaughtException(Thread t, Throwable e)
+        {
+            App.Log(e);
+        }
     }
 }


Implement SystemBitmap resizing in OSX

Implement SystemBitmap resizing in OSX

--- Common/SystemBitmap.cs
+++ Common/SystemBitmap.cs
@@ -88,13 +88,15 @@
             private System.Drawing.Graphics systemGraphics;
 #elif OSX
             private readonly Cairo.Context context;
+			private readonly SystemBitmap sysBmp;
 #endif

             public Graphics(SystemBitmap owner)
-            {
+            {
 #if WINDOWS
                 this.systemGraphics = System.Drawing.Graphics.FromImage(owner.bitmap);
 #elif OSX
+				this.sysBmp = owner;
                 this.context = new Cairo.Context(owner.bitmap);
 #endif
                 undisposed.Add(this);
@@ -112,11 +114,13 @@
             }

             public void Blit(SystemBitmap bmp, int x, int y, int stretchWidth, int stretchHeight)
-            {
+            {
 #if WINDOWS
                 this.systemGraphics.DrawImage(bmp.bitmap, x, y, stretchWidth, stretchHeight);
 #elif OSX
-                throw new Exception("Not implemented.");
+				this.context.Scale(1.0 * this.sysBmp.Width / bmp.bitmap.Width, 1.0 * this.sysBmp.Height / bmp.bitmap.Height);
+				this.context.SetSource(bmp.bitmap, x, y);
+				this.context.Paint();
 #endif
             }


ID -> file name extension.

ID -> file name extension.

--- Configuration/Paths.cs
+++ Configuration/Paths.cs
@@ -668,5 +668,13 @@
 				return xmlSer.Deserialize(data);
 			}
 		}
+
+		/// <summary>
+		/// Get file name for the specified id.
+		/// </summary>
+		/// <param name="id">Identifier.</param>
+		/// <returns>File name.</returns>
+		public static string GetFileName(this Guid id)
+			=> $"{id.ToString().Replace('-', '_')}{DefaultSettingsExt}";
 	}
 }


Fixed collider issue during placement with proximity sensor trap

--- Assets/Scripts/GameObjects/Traps/ProximitySensor.cs
+++ Assets/Scripts/GameObjects/Traps/ProximitySensor.cs
@@ -16,7 +16,7 @@
     private MeshRenderer meshRenderer;
     private static Transform[] players;
     private bool isActive = false;
-
+    private SphereCollider radiusCollider;
     public override string TrapName { get { return "Proximity Sensor"; } }
     #endregion

@@ -46,9 +46,10 @@
         //calc radius sqr
         radiusSqr = Mathf.Pow(radius, 2);
         transform.GetChild(0).localScale *= radius * 2;// transform.localScale.x;
-        SphereCollider radiusCollider = gameObject.AddComponent<SphereCollider>();
+        radiusCollider = gameObject.AddComponent<SphereCollider>();
         radiusCollider.radius = radius;
         radiusCollider.isTrigger = true;
+        radiusCollider.enabled = false;
     }
     #endregion

@@ -82,5 +83,10 @@
         }
         meshRenderer.material.color = Color.red;
     }
+
+    public override void TransitionToPlayPhase()
+    {
+        radiusCollider.enabled = true;
+    }
     #endregion
 }


Fix llVolumeDetect prims that are physical from not falling to the bottom of the sim and being returned (expected behavior).

--- Aurora/Physics/AuroraOpenDynamicsEngine/AODEPrim.cs
+++ Aurora/Physics/AuroraOpenDynamicsEngine/AODEPrim.cs
@@ -201,11 +201,7 @@
             _size = entity.Scale;
             _position = entity.AbsolutePosition;
             fakepos = false;
-            if (!entity.IsRoot)
-                _orientation = entity.ParentEntity.Rotation + entity.RotationOffset;
-            else
-                _orientation = entity.RotationOffset;
-            _orientation.Normalize ();
+            _orientation = entity.GetWorldRotation ();
             fakeori = false;
             _pbs = entity.Shape;
             _parent_entity = entity;
@@ -1412,8 +1408,6 @@
                     myrot.Y = fake.Y;
                     myrot.Z = fake.Z;
                     myrot.W = fake.W;
-                    Quaternion a = _parent_entity.ParentEntity.Rotation + _parent_entity.RotationOffset;
-                    a.Normalize ();
                     d.GeomSetQuaternion (prim_geom, ref myrot);
                 }
                 d.GeomSetPosition (prim_geom, newpos.X, newpos.Y, newpos.Z);
@@ -1693,7 +1687,7 @@
                     //Keep us out of terrain if possible
                     float terrainHeight = _parent_scene.GetTerrainHeightAtXY (Position.X, Position.Y);
                     float ourBasePos = (Position.Z - (Size.Z / 2));
-                    if (terrainHeight > ourBasePos)
+                    if (!_parent_entity.VolumeDetectActive && terrainHeight > ourBasePos)
                     {
                         //Scale it by surface - pos so that the object doesn't fly out of the terrain like a rocket
                         fz += gravZ * -2.5f * (terrainHeight - ourBasePos);//Get us up, but don't shoot us up


Revert "Sort invoice list (Fix #1329)"

Revert "Sort invoice list (Fix #1329)"

This reverts commit dc4f8a1fbe841c0824d545582cc46ae533e955c4.

--- BTCPayServer/Services/Invoices/InvoiceRepository.cs
+++ BTCPayServer/Services/Invoices/InvoiceRepository.cs
@@ -606,7 +606,7 @@
                 if (queryObject.IncludeEvents)
                     query = query.Include(o => o.Events);

-                var data = await query.OrderByDescending(i => i.Created).ToArrayAsync().ConfigureAwait(false);
+                var data = await query.ToArrayAsync().ConfigureAwait(false);
                 return data.Select(ToEntity).ToArray();
             }
         }


note a potential problem with certain file systems

--- AppendLog/AppendLog.cs
+++ AppendLog/AppendLog.cs
@@ -184,6 +184,12 @@

             public override void Close()
             {
+                //NOTE FS Atomicity: http://danluu.com/file-consistency/
+                //Moral: the OS can reorder writes such that the write at 0 could happen first, even if the write
+                //is called 2nd. If a crash/power loss happens btw the write at 0 and the writes to the end, the
+                //header is then just pointing at garbage. So call flush to sync data to disk, then write header.
+                Flush(true);
+
                 // write out the 32-bit block length
                 var length = (int)(Position - nextId);
                 buf[0] = (byte)(length         & 0xFFFF);


some small UI tweaks

some small UI tweaks

--- CAC/MainForm.cs
+++ CAC/MainForm.cs
@@ -203,11 +203,12 @@
             if (!InputsOutputs.GetList().Any())
             {
                 MessageBox.Show("Musíte nejdříve vytvořit testovací protokol!");
-                Tabs.SelectedIndex = 0;
+                Tabs.SelectedIndex = 1;
                 return;
             }

             //todo mozna vypnout UI?
+            Tabs.SelectedIndex = 0;
             SetListViewToGrepMode(); //todo GREP!
             butShowTestProgress.Visible = true;
             lbCodes.ClearSelected();


(CustomMediaFoundationReader): define API constants.

--- ArcFormats/AudioWMA.cs
+++ ArcFormats/AudioWMA.cs
@@ -132,13 +132,16 @@

         protected override IMFSourceReader CreateReader (MediaFoundationReaderSettings settings)
         {
+            const int MF_SOURCE_READER_ALL_STREAMS          = -2;
+            const int MF_SOURCE_READER_FIRST_AUDIO_STREAM   = -3;
+
             IMFByteStream byteStream;
             MFCreateMFByteStreamOnStream (new ComStream (m_stream), out byteStream);
             var source_reader = MediaFoundationApi.CreateSourceReaderFromByteStream (byteStream);

-            source_reader.SetStreamSelection (-2, false);
-            source_reader.SetStreamSelection (-3, true);
-            source_reader.SetCurrentMediaType (-3, IntPtr.Zero, new MediaType
+            source_reader.SetStreamSelection (MF_SOURCE_READER_ALL_STREAMS, false);
+            source_reader.SetStreamSelection (MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
+            source_reader.SetCurrentMediaType (MF_SOURCE_READER_FIRST_AUDIO_STREAM, IntPtr.Zero, new MediaType
             {
                 MajorType = MediaTypes.MFMediaType_Audio,
                 SubType = settings.RequestFloatOutput ? AudioSubtypes.MFAudioFormat_Float : AudioSubtypes.MFAudioFormat_PCM


Put translation instructions before content pages

--- PhotoStoryToBloomConverter/BloomModel/BloomDocument.cs
+++ PhotoStoryToBloomConverter/BloomModel/BloomDocument.cs
@@ -30,6 +30,11 @@
 			Dictionary<string, string> duplicateAudioFiles,
 			string alternateTitles)
 		{
+			// For now, we can use includeReferences to decide if we should add translation instructions.
+			// In the future we may need a separate switch.
+			if (Program.IncludeReferences)
+				AddTranslationInstructionPages(alternateTitles);
+
 			_metadata = BloomMetadata.DefaultBloomMetadata(bookName);
 			_bookData = BloomBookData.DefaultBloomBookData(bookName);
 			_duplicateAudioFiles = duplicateAudioFiles;
@@ -148,11 +153,6 @@
 			else
 				CreditsAndCoverExtractor.CreateMapFile();

-			// For now, we can use includeReferences to decide if we should add translation instructions.
-			// In the future we may need a separate switch.
-			if (Program.IncludeReferences)
-				AddTranslationInstructionPages(alternateTitles);
-
 			if (_imageCopyrightAndLicense != CreditsAndCoverExtractor.CreditsType.Unknown)
 			{
 				//Because credits may have been at end of book, go back through and set image credits if we extracted some.


Use 'CurrentName' to set the initial filename for unsaved files.

The docs indicate that this is intended for files that don't exist yet, so hopefully this will work consistently now on all platforms.

This is related to the change in 9d6ac259

Bug: #1909664

--- Pinta/Actions/File/SaveDocumentImplementationAction.cs
+++ Pinta/Actions/File/SaveDocumentImplementationAction.cs
@@ -81,7 +81,11 @@
 			};

 			fcd.SetCurrentFolder (PintaCore.System.GetDialogDirectory ());
-			fcd.SetFilename (document.PathAndFileName);
+
+			if (document.HasFile)
+				fcd.SetFilename (document.PathAndFileName);
+			else
+				fcd.CurrentName = document.Filename;

 			var filetypes = new Dictionary<FileFilter, FormatDescriptor> ();


Added overrideable method for setting hub event handlers.

--- PocketHub.Client.Lib/ServiceProviders/HubClientBase.cs
+++ PocketHub.Client.Lib/ServiceProviders/HubClientBase.cs
@@ -90,7 +90,7 @@
             HandleConnectionEvents();

             _hub = _conn.CreateHubProxy(HubName);
-            HandleHubEvents();
+            SetEventHandlers(_hub);

             try
             {
@@ -219,10 +219,14 @@
         }

-        private void HandleHubEvents()
-        {
-            _hub.On<string, string>("AddMessage", (nme, msg)
-                => SetStatus($"[{nme}]  {msg}"));
+        /// <summary>
+        /// Safe to fully override because base method is empty.
+        /// </summary>
+        /// <param name="hub"></param>
+        protected virtual void SetEventHandlers(IHubProxy hub)
+        {
+            //_hub.On<string, string>("AddMessage", (nme, msg)
+            //    => SetStatus($"[{nme}]  {msg}"));
         }


added workgroup non-people management info

--- Purchasing.Web/Views/WorkgroupManagement/Manage.cshtml
+++ Purchasing.Web/Views/WorkgroupManagement/Manage.cshtml
@@ -2,6 +2,14 @@

 @{
 	ViewBag.Title = "Manage Workgroup";
+}
+
+@helper RowFor(string name, int count){
+

+        @name:
+        @count
+        Edit
+

 }

 @section SubNav
@@ -36,50 +44,10 @@

Workgroup Associations

-

-
-                Organizations:
-
-
-                @Model.OrganizationCount
-
-
-                Edit
-
-

-

-
-                Accounts:
-
-
-                @Model.AccountCount
-
-
-                Edit
-
-

-

-
-                Vendors:
-
-
-                @Model.VendorCount
-
-
-                Edit
-
-

-

-
-                Addresses:
-
-
-                @Model.AddressCount
-
-
-                Edit
-
-

+        @RowFor("Organizations", Model.OrganizationCount)
+        @RowFor("Accounts", Model.AccountCount)
+        @RowFor("Vendors", Model.VendorCount)
+        @RowFor("Addresses", Model.AddressCount)


Fix unit test warnings

Fix unit test warnings

--- Quamotion.TurboJpegWrapper.Tests/TJTransformerTests.cs
+++ Quamotion.TurboJpegWrapper.Tests/TJTransformerTests.cs
@@ -41,7 +41,7 @@
                 var result = _transformer.Transform(data.Item2, transforms, TJFlags.NONE);

                 Assert.NotNull(result);
-                Assert.NotNull(result.Length == 1);
+                Assert.Single(result);

                 var file = Path.Combine(OutDirectory, "gray_" + Path.GetFileName(data.Item1));
                 File.WriteAllBytes(file, result[0]);
@@ -128,7 +128,7 @@

                 var result = _transformer.Transform(data.Item2, transforms, TJFlags.NONE);
                 Assert.NotNull(result);
-                Assert.NotNull(result.Length == 1);
+                Assert.NotEmpty(result);

                 for (var idx = 0; idx < result.Length; idx++)
                 {


beerfish

beerfish

--- Assets/Scripts/Fish.cs
+++ Assets/Scripts/Fish.cs
@@ -7,6 +7,8 @@

 	public float speedY;

+	public Sprite beer;
+
 	private int rotate;

 	// Use this for initialization
@@ -14,6 +16,11 @@
 		player = GameObject.Find ("Player").GetComponent<PlayerController>();

 		rotate = Random.Range (1, 3);
+
+		int intbeer = Random.Range (0, 100);
+
+		if (intbeer == 50)
+			this.GetComponent<SpriteRenderer> ().sprite = beer;

 		if (rotate == 2) {
 			Vector3 scale = this.transform.localScale;


Pass DocumentID to new object in viewmodel

--- R7.University/Controls/ViewModels/DocumentViewModel.cs
+++ R7.University/Controls/ViewModels/DocumentViewModel.cs
@@ -96,13 +96,14 @@
         public DocumentInfo NewDocumentInfo ()
         {
             return new DocumentInfo {
+                DocumentID = DocumentID,
+                DocumentTypeID = DocumentTypeID,
+                ItemID = ItemID,
                 Title = Title,
-                ItemID = ItemID,
                 Url = Url,
                 SortIndex = SortIndex,
                 StartDate = StartDate,
-                EndDate = EndDate,
-                DocumentTypeID = DocumentTypeID
+                EndDate = EndDate
             };
         }
     }


implemented getdocumentcontent

implemented getdocumentcontent

--- Dedbugger/DebuggerCore.cs
+++ Dedbugger/DebuggerCore.cs
@@ -55,6 +55,7 @@
         private NamedPipeClientStream Pipe;
         private List<BreakpointInfo> BreakpointInfos;
         private asapJson.JsonNode LastCallstack;
+        private string LastDocumentContent;
         private const int MinimalDebuggerBuild = 23;

         public Thread PipeReadThread { get; private set; }
@@ -69,6 +70,7 @@
         {
             Messages = new ConcurrentBag<JsonNode>();
             this.Pipe = null;
+            this.this.LastDocumentContent = string.Empty;
         }

         public bool Attach()
@@ -191,6 +193,7 @@
                                         var fileOffsetNode = error.GetValue_Object()["fileOffset"];
                                         var errorMessage = error.GetValue_Object()["message"];//ToDo: display to user
                                         var fileContent = error.GetValue_Object()["content"];//File content in case we don't have that file
+                                        this.LastDocumentContent = fileContent.GetValue_String();
                                         var line = (int)fileOffsetNode.GetValue_Array()[0].GetValue_Number();
                                         var col = (int)fileOffsetNode.GetValue_Array()[2].GetValue_Number();
                                         this.OnHalt?.Invoke(this, new OnHaltEventArgs(error.GetValue_Object()["filename"].GetValue_String(), line, col));
@@ -432,7 +435,7 @@

         public string GetDocumentContent(string armapath)
         {
-            throw new NotImplementedException();
+            return this.LastDocumentContent;
         }
     }
 }


note a bug involving moving non-live paths

--- Assets/Scripts/Path.cs
+++ Assets/Scripts/Path.cs
@@ -223,6 +223,7 @@
 		if (time < g.timeSim) {
 			// move non-live path if in past
 			// if this path already isn't live, a better approach is removing later segments and moves then moving this path, like pre-stacking versions
+			// TODO: this fails if moving non-live unit immediately when it's made (b/c parent is ambiguous), or moving non-live unit when resources are negative
 			if (!makePath (time, units)) throw new SystemException("make non-live path failed when moving units");
 			path2 = g.paths.Last ();
 		}


Fixed but with coins in wrong part of rooms if monster in the way

--- Assets/Scripts/Room.cs
+++ Assets/Scripts/Room.cs
@@ -373,7 +373,7 @@
                 var coord = Coordinate.FromPosition(candidates[i], width);
                 if (PermissableDoorPosition(coord))
                 {
-                    var path = RoomSearch.FindShortestPath(this, upStairs, downStairs);
+                    var path = RoomSearch.FindShortestPath(this, upStairs, downStairs, false, TileType.Walkable, TileType.SpikeTrap, TileType.StairsUp, TileType.StairsDown);
                     if (path.Length > 0 && !System.Array.Exists<Coordinate>(path, e => e == coord)) {
                         SetTileType(coord, TileType.Door);
                         Coordinate deadEnd;