diff --git a/Pilz.Collections/Pilz.Collections.vbproj b/Pilz.Collections/Pilz.Collections.vbproj index b0fc5b8..654c6b2 100644 --- a/Pilz.Collections/Pilz.Collections.vbproj +++ b/Pilz.Collections/Pilz.Collections.vbproj @@ -98,7 +98,7 @@ - + diff --git a/Pilz.Collections/SimpleHistory/ObjectValueType.vb b/Pilz.Collections/SimpleHistory/ObjectValueType.vb new file mode 100644 index 0000000..8438552 --- /dev/null +++ b/Pilz.Collections/SimpleHistory/ObjectValueType.vb @@ -0,0 +1,12 @@ +Namespace SimpleHistory + + ''' + ''' Specify which member types you would include. + ''' + Public Enum ObjectValueType + None = 0 + Field = 1 + [Property] = 2 + End Enum + +End Namespace \ No newline at end of file diff --git a/Pilz.Collections/SimpleHistory/SimpleHistory.vb b/Pilz.Collections/SimpleHistory/SimpleHistory.vb index 74c7339..a4d7d88 100644 --- a/Pilz.Collections/SimpleHistory/SimpleHistory.vb +++ b/Pilz.Collections/SimpleHistory/SimpleHistory.vb @@ -32,15 +32,12 @@ Namespace SimpleHistory Dim ret As HistoryPoint If stackPast.Count > 0 Then - Dim hp As HistoryPoint = stackPast.Pop hp.Undo() stackFuture.Push(hp) ret = hp - Else ret = Nothing - End If Return ret @@ -53,15 +50,12 @@ Namespace SimpleHistory Dim ret As HistoryPoint If stackFuture.Count > 0 Then - Dim hp As HistoryPoint = stackFuture.Pop hp.Redo() stackPast.Push(hp) ret = hp - Else ret = Nothing - End If Return ret diff --git a/Pilz.Configuration/Pilz.Configuration.vbproj b/Pilz.Configuration/Pilz.Configuration.vbproj index 6d1c540..5f5d09f 100644 --- a/Pilz.Configuration/Pilz.Configuration.vbproj +++ b/Pilz.Configuration/Pilz.Configuration.vbproj @@ -45,7 +45,7 @@ - ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll diff --git a/Pilz.Configuration/packages.config b/Pilz.Configuration/packages.config index 7f83af3..93b0be8 100644 --- a/Pilz.Configuration/packages.config +++ b/Pilz.Configuration/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Pilz.Drawing.Drawing3D.OpenGLFactory.vbproj b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Pilz.Drawing.Drawing3D.OpenGLFactory.vbproj index 1829246..ad9d693 100644 --- a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Pilz.Drawing.Drawing3D.OpenGLFactory.vbproj +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Pilz.Drawing.Drawing3D.OpenGLFactory.vbproj @@ -43,11 +43,11 @@ On - - ..\packages\OpenTK.3.0.1\lib\net20\OpenTK.dll + + ..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll - - ..\packages\OpenTK.GLControl.3.0.1\lib\net20\OpenTK.GLControl.dll + + ..\packages\OpenTK.GLControl.3.1.0\lib\net20\OpenTK.GLControl.dll diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.vb index 2990e15..3744f88 100644 --- a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.vb +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.vb @@ -23,7 +23,6 @@ Namespace PreviewN Private camMtx As Matrix4 = Matrix4.Identity Private savedCamPos As New Vector3 Private _isMouseDown As Boolean = False - 'Private myPressedKeys As New List(Of Keys) Private isDeactivated As Boolean = False Private ReadOnly myModels As New Dictionary(Of Object3D, Renderer) @@ -32,12 +31,6 @@ Namespace PreviewN Public Property Scaling As Single = 500.0F Public Property ClearColor As Color = Color.CornflowerBlue - 'Public ReadOnly Property PressedKeys As IReadOnlyList(Of Keys) - ' Get - ' Return myPressedKeys - ' End Get - 'End Property - Public ReadOnly Property Camera As Camera Get Return MyCamera @@ -56,9 +49,14 @@ Namespace PreviewN End Get End Property + Public ReadOnly Property GLControl As Control + Get + Return glControl1 + End Get + End Property + Private ReadOnly Property IsStrgPressed As Boolean Get - 'Return myPressedKeys.Contains(Keys.ControlKey) Dim state As KeyboardState = Keyboard.GetState() Return state(Key.ControlLeft) OrElse state(Key.ControlRight) End Get @@ -66,7 +64,6 @@ Namespace PreviewN Private ReadOnly Property IsShiftPressed As Boolean Get - 'Return myPressedKeys.Contains(Keys.ShiftKey) Dim state As KeyboardState = Keyboard.GetState() Return state(Key.ShiftLeft) OrElse state(Key.ShiftRight) End Get @@ -142,7 +139,6 @@ Namespace PreviewN Public Sub UpdateView() glControl1.Invalidate() - 'glControl1.Update() End Sub Public Function AddModel(obj As Object3D) As Renderer @@ -226,38 +222,8 @@ Namespace PreviewN Next glControl1.SwapBuffers() - - 'If Not IsMouseDown AndAlso obj3d IsNot Nothing Then - ' e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias - ' e.Graphics.DrawString(GetModelInfoAsString, New Font(FontFamily.GenericSerif, 10), New SolidBrush(Panel1.ForeColor), New Drawing.Point(10, 10)) - 'End If End Sub - Private Function GetModelInfoAsString() As String - Dim matsCount As Long = 0 - Dim facesCount As Long = 0 - Dim vertsCount As Long = 0 - Dim vcCount As Long = 0 - Dim uvCount As Long = 0 - - For Each obj3d As Object3D In myModels.Keys - matsCount += obj3d.Materials.Count - For Each m As Mesh In obj3d.Meshes - vertsCount += m.Vertices.Count - facesCount += m.Faces.Count - vcCount += m.VertexColors.Count - uvCount += m.UVs.Count - Next - Next - - Return String.Format("Materials:{0}{1} -Faces:{0}{0}{2} -Vertices:{0}{3} -Vertex Colors{0}{4} -UVs:{0}{0}{5}", - vbTab, matsCount, facesCount, vertsCount, vcCount, uvCount) - End Function - Private Sub glControl1_Resize(sender As Object, e As EventArgs) Handles glControl1.Resize glControl1.Context.Update(glControl1.WindowInfo) GL.Viewport(0, 0, glControl1.Width, glControl1.Height) @@ -293,44 +259,10 @@ UVs:{0}{0}{5}", End If End Sub - 'Public Sub HandlesOnKeyDown(sender As Object, e As KeyEventArgs) Handles glControl1.KeyDown - ' If Not myPressedKeys.Contains(e.KeyCode) Then myPressedKeys.Add(e.KeyCode) - 'End Sub - - 'Public Sub HandlesOnKeyUp(sender As Object, e As KeyEventArgs) Handles MyBase.KeyUp - ' If myPressedKeys.Contains(e.KeyCode) Then myPressedKeys.Remove(e.KeyCode) - 'End Sub - Public Sub MoveCameraViaWASDQE() Dim moveSpeed As Integer = Convert.ToInt32(Math.Round((If(IsShiftPressed, 60, 30)) * (MyCamera.CamSpeedMultiplier), 0)) Dim allowCamMove As Boolean = Not (IsMouseDown AndAlso IsShiftPressed) - 'For Each k As Keys In myPressedKeys - ' If allowCamMove Then - ' Select Case k - ' Case Keys.W - ' 'camera.Move(moveSpeed, moveSpeed, camMtx) - ' MyCamera.UpdateCameraMatrixWithScrollWheel(moveSpeed, camMtx) - ' savedCamPos = MyCamera.Position - ' Case Keys.S - ' 'camera.Move(-moveSpeed, -moveSpeed, camMtx) - ' MyCamera.UpdateCameraMatrixWithScrollWheel(-moveSpeed, camMtx) - ' savedCamPos = MyCamera.Position - ' Case Keys.A - ' 'camera.Move(-moveSpeed, 0, camMtx) - ' MyCamera.UpdateCameraOffsetDirectly(-moveSpeed, 0, camMtx) - ' Case Keys.D - ' 'camera.Move(moveSpeed, 0, camMtx) - ' MyCamera.UpdateCameraOffsetDirectly(moveSpeed, 0, camMtx) - ' Case Keys.E - ' 'camera.Move(0, -moveSpeed, camMtx) - ' MyCamera.UpdateCameraOffsetDirectly(0, -moveSpeed, camMtx) - ' Case Keys.Q - ' 'camera.Move(0, moveSpeed, camMtx) - ' MyCamera.UpdateCameraOffsetDirectly(0, moveSpeed, camMtx) - ' End Select - ' End If - 'Next If allowCamMove Then Dim state As KeyboardState = Keyboard.GetState diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/packages.config b/Pilz.Drawing.Drawing3D.OpenGLRenderer/packages.config index d8280d7..0a27f2e 100644 --- a/Pilz.Drawing.Drawing3D.OpenGLRenderer/packages.config +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/packages.config @@ -1,6 +1,6 @@  - - + + \ No newline at end of file diff --git a/Pilz.Drawing/HelpfulDrawingFunctions.vb b/Pilz.Drawing/HelpfulDrawingFunctions.vb index b7d74d3..5fb2c28 100644 --- a/Pilz.Drawing/HelpfulDrawingFunctions.vb +++ b/Pilz.Drawing/HelpfulDrawingFunctions.vb @@ -1,9 +1,9 @@ Imports System.Drawing Imports System.Drawing.Drawing2D -Public Class HelpfulDrawingFunctions +Public Module HelpfulDrawingFunctions - Public Shared Function IsPointInRectangle(p As PointF, rect As RectangleF) As Boolean + Public Function IsPointInRectangle(p As PointF, rect As RectangleF) As Boolean Dim bList As New List(Of Boolean) bList.Add(p.X > rect.Left) @@ -14,11 +14,20 @@ Public Class HelpfulDrawingFunctions Return Not bList.Contains(False) End Function - Public Shared Function OverlapsTwoRectangles(a As RectangleF, b As RectangleF) As Boolean + Public Function OverlapsTwoRectangles(a As RectangleF, b As RectangleF) As Boolean Return a.IntersectsWith(b) 'RectangleF.Intersect(a, b) <> RectangleF.Empty End Function - Public Shared Function GetRectangle(p1 As PointF, p2 As PointF) As RectangleF + Public Function RectangleContainsRectangle(parent As RectangleF, child As RectangleF) As Boolean + Return parent.Contains(child) + 'Return _ + ' IsPointInRectangle(New PointF(child.Top, child.Left), parent) AndAlso + ' IsPointInRectangle(New PointF(child.Top, child.Right), parent) AndAlso + ' IsPointInRectangle(New PointF(child.Bottom, child.Left), parent) AndAlso + ' IsPointInRectangle(New PointF(child.Bottom, child.Right), parent) + End Function + + Public Function GetRectangle(p1 As PointF, p2 As PointF) As RectangleF Dim rect As New RectangleF Dim startIsEnd As Boolean = p1.X > p2.X AndAlso p1.Y > p2.Y @@ -37,5 +46,5 @@ Public Class HelpfulDrawingFunctions Return rect End Function -End Class +End Module diff --git a/Pilz.Networking/ConnectionManagerBase.vb b/Pilz.Networking/ConnectionManagerBase.vb new file mode 100644 index 0000000..7c0fa48 --- /dev/null +++ b/Pilz.Networking/ConnectionManagerBase.vb @@ -0,0 +1,84 @@ +Imports System.IO +Imports Newtonsoft.Json.Linq + +Public MustInherit Class ConnectionManagerBase + + Private listening As Boolean = False + + Public ReadOnly Property Port As Integer + + Public Event RetriveData(manager As ConnectionManagerBase, senderIP As String, cmd As String, content As Object) + + Public Property IsListening As Boolean + Get + Return listening + End Get + Protected Set(value As Boolean) + listening = value + End Set + End Property + + Public Sub New(port As Integer) + Me.Port = port + End Sub + + Protected Overrides Sub Finalize() + [Stop]() + End Sub + + Public MustOverride Sub Start() + Public MustOverride Sub [Stop]() + Public MustOverride Sub Send(empfängerIP As String, cmd As String, content As Object) + + Public Overridable Sub Send(empfängerIP As String, cmd As String) + Send(empfängerIP, cmd, String.Empty) + End Sub + + Public Overridable Sub Send(empfängerIP As String, cmd As String, info As String) + Send(empfängerIP, cmd, CObj(info)) + End Sub + + Public Sub RaiseRetriveData(senderIP As String, cmd As String, content As Object) + RaiseEvent RetriveData(Me, senderIP, cmd, content) + End Sub + + Protected Shared Function EncodeToBytes(cmd As String, content As Object) As Byte() + Dim ms As New MemoryStream() + Dim bw As New BinaryWriter(ms) + Dim obj As New JObject + + 'Write header + obj("Cmd") = cmd + obj("ContentType") = content?.GetType?.ToString + + 'Content + obj("Content") = JToken.FromObject(content) + + 'Write Json to MemoryStream + bw.Write(Text.Encoding.Default.GetBytes(obj.ToString)) + + 'Get Buffer Bytes + Dim buf As Byte() = ms.ToArray + ms.Close() + + Return buf + End Function + + Protected Shared Function DecodeFromBytes(buf As Byte()) As (cmd As String, content As Object) + Dim contentstring As String = Text.Encoding.Default.GetString(buf) + Dim content As Object = Nothing + Dim contentobj As JObject = JObject.Parse(contentstring) + + Dim cmd As String = contentobj("Cmd") + Dim contenttypestring As String = contentobj("ContentType") + Dim contentlinq As JToken = contentobj("Content") + + If Not String.IsNullOrEmpty(contenttypestring) Then + Dim contenttype As Type = Type.GetType(contenttypestring) + content = contentlinq.ToObject(contenttype) + End If + + Return (cmd, content) + End Function + +End Class diff --git a/Pilz.Networking/My Project/Application.Designer.vb b/Pilz.Networking/My Project/Application.Designer.vb new file mode 100644 index 0000000..88dd01c --- /dev/null +++ b/Pilz.Networking/My Project/Application.Designer.vb @@ -0,0 +1,13 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + diff --git a/Pilz.Networking/My Project/Application.myapp b/Pilz.Networking/My Project/Application.myapp new file mode 100644 index 0000000..758895d --- /dev/null +++ b/Pilz.Networking/My Project/Application.myapp @@ -0,0 +1,10 @@ + + + false + false + 0 + true + 0 + 1 + true + diff --git a/Pilz.Networking/My Project/AssemblyInfo.vb b/Pilz.Networking/My Project/AssemblyInfo.vb new file mode 100644 index 0000000..c81f2f8 --- /dev/null +++ b/Pilz.Networking/My Project/AssemblyInfo.vb @@ -0,0 +1,35 @@ +Imports System +Imports System.Reflection +Imports System.Runtime.InteropServices + +' Allgemeine Informationen über eine Assembly werden über die folgenden +' Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +' die einer Assembly zugeordnet sind. + +' Werte der Assemblyattribute überprüfen + + + + + + + + + + +'Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird. + + +' Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +' +' Hauptversion +' Nebenversion +' Buildnummer +' Revision +' +' Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +' übernehmen, indem Sie "*" eingeben: +' + + + diff --git a/Pilz.Networking/My Project/Resources.Designer.vb b/Pilz.Networking/My Project/Resources.Designer.vb new file mode 100644 index 0000000..a2b623f --- /dev/null +++ b/Pilz.Networking/My Project/Resources.Designer.vb @@ -0,0 +1,62 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My.Resources + + 'This class was auto-generated by the StronglyTypedResourceBuilder + 'class via a tool like ResGen or Visual Studio. + 'To add or remove a member, edit your .ResX file then rerun ResGen + 'with the /str option, or rebuild your VS project. + ''' + ''' A strongly-typed resource class, for looking up localized strings, etc. + ''' + _ + Friend Module Resources + + Private resourceMan As Global.System.Resources.ResourceManager + + Private resourceCulture As Global.System.Globalization.CultureInfo + + ''' + ''' Returns the cached ResourceManager instance used by this class. + ''' + _ + Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager + Get + If Object.ReferenceEquals(resourceMan, Nothing) Then + Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Pilz.Networking.Resources", GetType(Resources).Assembly) + resourceMan = temp + End If + Return resourceMan + End Get + End Property + + ''' + ''' Overrides the current thread's CurrentUICulture property for all + ''' resource lookups using this strongly typed resource class. + ''' + _ + Friend Property Culture() As Global.System.Globalization.CultureInfo + Get + Return resourceCulture + End Get + Set(ByVal value As Global.System.Globalization.CultureInfo) + resourceCulture = value + End Set + End Property + End Module +End Namespace diff --git a/Pilz.Networking/My Project/Resources.resx b/Pilz.Networking/My Project/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Pilz.Networking/My Project/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Pilz.Networking/My Project/Settings.Designer.vb b/Pilz.Networking/My Project/Settings.Designer.vb new file mode 100644 index 0000000..ee067b4 --- /dev/null +++ b/Pilz.Networking/My Project/Settings.Designer.vb @@ -0,0 +1,73 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + _ + Partial Friend NotInheritable Class MySettings + Inherits Global.System.Configuration.ApplicationSettingsBase + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings) + +#Region "My.Settings Auto-Save Functionality" +#If _MyType = "WindowsForms" Then + Private Shared addedHandler As Boolean + + Private Shared addedHandlerLockObject As New Object + + _ + Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) + If My.Application.SaveMySettingsOnExit Then + My.Settings.Save() + End If + End Sub +#End If +#End Region + + Public Shared ReadOnly Property [Default]() As MySettings + Get + +#If _MyType = "WindowsForms" Then + If Not addedHandler Then + SyncLock addedHandlerLockObject + If Not addedHandler Then + AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings + addedHandler = True + End If + End SyncLock + End If +#End If + Return defaultInstance + End Get + End Property + End Class +End Namespace + +Namespace My + + _ + Friend Module MySettingsProperty + + _ + Friend ReadOnly Property Settings() As Global.Pilz.Networking.My.MySettings + Get + Return Global.Pilz.Networking.My.MySettings.Default + End Get + End Property + End Module +End Namespace diff --git a/Pilz.Networking/My Project/Settings.settings b/Pilz.Networking/My Project/Settings.settings new file mode 100644 index 0000000..85b890b --- /dev/null +++ b/Pilz.Networking/My Project/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Pilz.Networking/NetworkFeatures.vb b/Pilz.Networking/NetworkFeatures.vb new file mode 100644 index 0000000..3c2f5df --- /dev/null +++ b/Pilz.Networking/NetworkFeatures.vb @@ -0,0 +1,54 @@ +Imports System.Net +Imports System.Net.NetworkInformation +Imports System.Net.Sockets + +Public Module NetworkFeatures + + Public Function GetIPFromHost(hostName As String) As IPAddress + Return Dns.GetHostAddresses(hostName).FirstOrDefault(Function(n) n.AddressFamily = AddressFamily.InterNetwork) + End Function + + Public Function GetHostFromIP(ip As String) + Return Dns.GetHostEntry(ip)?.HostName + End Function + + Public Function GetLocalIPInformations() As UnicastIPAddressInformation + Dim addr As UnicastIPAddressInformation = Nothing + + For Each adapter As NetworkInterface In NetworkInterface.GetAllNetworkInterfaces + If addr Is Nothing AndAlso adapter.OperationalStatus = OperationalStatus.Up AndAlso adapter.NetworkInterfaceType <> NetworkInterfaceType.Tunnel AndAlso adapter.NetworkInterfaceType <> NetworkInterfaceType.Loopback Then + For Each uni As UnicastIPAddressInformation In adapter.GetIPProperties.UnicastAddresses + If addr Is Nothing AndAlso uni.Address.AddressFamily = AddressFamily.InterNetwork Then + addr = uni + End If + Next + End If + Next + + Return addr + End Function + + Public Function GetLocalIPAddress() As IPAddress + Return GetLocalIPInformations()?.Address + End Function + + Public Function GetLocalIPv4Mask() As IPAddress + Return GetLocalIPInformations()?.IPv4Mask + End Function + + Public Function GetLocalBoradcastIP(ipInfo As UnicastIPAddressInformation) As IPAddress + Dim ip As IPAddress = Nothing + Dim myIPBytes As Byte() = ipInfo.Address.GetAddressBytes + Dim subnetBytes As Byte() = ipInfo.IPv4Mask.GetAddressBytes + Dim broadcastBytes As Byte() = New Byte(myIPBytes.Length - 1) {} + + For i As Integer = 0 To subnetBytes.Length - 1 + broadcastBytes(i) = myIPBytes(i) Or Not subnetBytes(i) + Next + + ip = New IPAddress(broadcastBytes) + + Return ip + End Function + +End Module diff --git a/Pilz.Networking/Pilz.Networking.vbproj b/Pilz.Networking/Pilz.Networking.vbproj new file mode 100644 index 0000000..20c6cb5 --- /dev/null +++ b/Pilz.Networking/Pilz.Networking.vbproj @@ -0,0 +1,114 @@ + + + + + Debug + AnyCPU + {4584B121-09C6-40AC-849B-7E410125EF66} + Library + Pilz.Networking + Pilz.Networking + 512 + Windows + v4.5 + true + + + true + full + true + true + bin\Debug\ + Pilz.Networking.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + pdbonly + false + true + true + bin\Release\ + Pilz.Networking.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + On + + + Binary + + + Off + + + On + + + + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + + + + + ..\..\ConsoleApp2\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll + + + + + + + + + + + + + + + + + + + + + + + True + Application.myapp + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + + + + VbMyResourcesResXFileCodeGenerator + Resources.Designer.vb + My.Resources + Designer + + + + + MyApplicationCodeGenerator + Application.Designer.vb + + + SettingsSingleFileGenerator + My + Settings.Designer.vb + + + + + \ No newline at end of file diff --git a/Pilz.Networking/TCPManager.vb b/Pilz.Networking/TCPManager.vb new file mode 100644 index 0000000..fe032c5 --- /dev/null +++ b/Pilz.Networking/TCPManager.vb @@ -0,0 +1,83 @@ +Imports System.IO +Imports System.Net +Imports System.Net.NetworkInformation +Imports System.Net.Sockets +Imports Newtonsoft.Json.Linq + +Public Class TCPManager + Inherits ConnectionManagerBase + + Private ReadOnly listener As TcpListener + Public Property BufferSize As Integer = 10240 + + Public Sub New(port As Integer) + MyBase.New(port) + listener = New TcpListener(IPAddress.Any, port) + End Sub + + Public Overrides Sub Start() + If Not IsListening Then + listener.Start() + IsListening = True + Task.Run(AddressOf CheckRetriveData) + End If + End Sub + + ''' + ''' Stop listening on given port. + ''' + Public Overrides Sub [Stop]() + If IsListening Then + IsListening = False + listener.Stop() + End If + End Sub + + Private Sub CheckRetriveData() + Do While IsListening + If listener.Pending Then + Dim tcp As TcpClient = listener.AcceptTcpClient() + Dim ip As String = CType(tcp.Client.RemoteEndPoint, IPEndPoint).Address.ToString + Dim Stream As NetworkStream = tcp.GetStream + Dim buf As Byte() = New Byte(BufferSize - 1) {} + + tcp.ReceiveBufferSize = BufferSize + Stream.Read(buf, 0, buf.Length) + + Dim contentstring As String = Text.Encoding.Default.GetString(buf) + Dim content As Object = Nothing + Dim cmd As String = String.Empty + + Try + Dim res = DecodeFromBytes(buf) + cmd = res.cmd + content = res.content + Catch ex As Exception + End Try + + tcp.Close() + + RaiseRetriveData(ip, cmd, content) + End If + Loop + End Sub + + Public Overrides Sub Send(empfängerIP As String, cmd As String, content As Object) + Dim ep As New IPEndPoint(GetIPFromHost(empfängerIP).MapToIPv4, Port) + Dim tcp As New TcpClient + + tcp.SendBufferSize = BufferSize + tcp.Connect(ep) + + Dim stream As NetworkStream = tcp.GetStream() + Dim buf As Byte() = EncodeToBytes(cmd, content) + + 'Send Data + stream.Write(buf, 0, buf.Length) + stream.Flush() + + tcp.Client.Shutdown(SocketShutdown.Both) + tcp.Close() + End Sub + +End Class diff --git a/Pilz.Networking/UDPManager.vb b/Pilz.Networking/UDPManager.vb new file mode 100644 index 0000000..01b57d0 --- /dev/null +++ b/Pilz.Networking/UDPManager.vb @@ -0,0 +1,94 @@ +Imports System.IO +Imports System.Net +Imports System.Net.NetworkInformation +Imports System.Net.Sockets +Imports System.Threading +Imports Newtonsoft.Json.Linq + +Public Class UDPManager + Inherits ConnectionManagerBase + + Private ReadOnly client As UdpClient + Private listenTask As Task = Nothing + Private ReadOnly cancelTokenSource As New CancellationTokenSource + Private ReadOnly cancelToken As CancellationToken = cancelTokenSource.Token + + Public Sub New(port As Integer) + MyBase.New(port) + client = New UdpClient(port) + End Sub + + Protected Overrides Sub Finalize() + MyBase.Finalize() + client.Client.Shutdown(SocketShutdown.Both) + client.Close() + End Sub + + Public Overrides Sub Start() + If Not IsListening Then + StartInternal() + End If + End Sub + + Private Sub StartInternal() + IsListening = True + listenTask = Task.Run( + Sub() + Try + RetriveAnyData(cancelToken) + Catch ex As Exception + IsListening = False + End Try + End Sub) + End Sub + + ''' + ''' Stop listening on given port. + ''' + Public Overrides Sub [Stop]() + If IsListening Then + IsListening = False + cancelTokenSource.Cancel() + listenTask.Wait() + End If + End Sub + + Private Sub RetriveAnyData(ct As CancellationToken) + Dim doExit = Sub() ct.ThrowIfCancellationRequested() + Dim receiveTask As Task(Of UdpReceiveResult) = client.ReceiveAsync() + + 'Wait for the data and cancel if requested + receiveTask.Wait(ct) + + Dim buf As Byte() = receiveTask.Result.Buffer + Dim ip As String = receiveTask.Result.RemoteEndPoint.Address.ToString + Dim cmd As String = String.Empty + Dim content As Object = Nothing + + doExit() + + Try + Dim res = DecodeFromBytes(buf) + cmd = res.cmd + content = res.content + Catch ex As Exception + End Try + + RaiseRetriveData(ip, cmd, content) + + doExit() + StartInternal() + End Sub + + Public Overrides Sub Send(empfängerIP As String, cmd As String, content As Object) + Dim ep As New IPEndPoint(GetIPFromHost(empfängerIP).MapToIPv4, Port) + Dim udp As New UdpClient + Dim buf As Byte() = EncodeToBytes(cmd, content) + + udp.Connect(ep) + udp.Send(buf, buf.Length) + udp.Client.Shutdown(SocketShutdown.Both) + udp.Close() + End Sub + +End Class diff --git a/Pilz.Networking/packages.config b/Pilz.Networking/packages.config new file mode 100644 index 0000000..5f639a6 --- /dev/null +++ b/Pilz.Networking/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Pilz.Simple3DFileParser/Model/Mesh.vb b/Pilz.Simple3DFileParser/Model/Mesh.vb index 53dfa0b..392c850 100644 --- a/Pilz.Simple3DFileParser/Model/Mesh.vb +++ b/Pilz.Simple3DFileParser/Model/Mesh.vb @@ -8,34 +8,35 @@ Public Class Mesh Public ReadOnly Property VertexColors As New List(Of VertexColor) Public ReadOnly Property Faces As New List(Of Face) - Friend Function GetCenterModelAvg() As Vector3 + Public Sub CenterModel() + CenterModel({Me}) + End Sub + + Public Shared Sub CenterModel(meshes As IEnumerable(Of Mesh)) Dim avgX As Integer = 0 Dim avgY As Integer = 0 Dim avgZ As Integer = 0 + Dim vertsCount As Long = 0 - For Each v As Vertex In Vertices - avgX += v.X - avgY += v.Y - avgZ += v.Z + For Each m As Mesh In meshes + For Each v As Vertex In m.Vertices + avgX += v.X + avgY += v.Y + avgZ += v.Z + Next + vertsCount += m.Vertices.Count Next - Return New Vector3(avgX, avgY, avgZ) - End Function + Dim avg As New Vector3(avgX, avgY, avgZ) + avg /= New Vector3(vertsCount) - Public Sub CenterModel() - Dim avg As Vector3 = GetCenterModelAvg() - - avg /= New Vector3(Vertices.Count) - - CenterModel(avg) - End Sub - - Public Sub CenterModel(avg As Vector3) - For Each v As Vertex In Vertices - v.X -= avg.X - v.Y -= avg.Y - v.Z -= avg.Z + For Each m As Mesh In meshes + For Each v As Vertex In m.Vertices + v.X -= avg.X + v.Y -= avg.Y + v.Z -= avg.Z + Next Next End Sub -End Class \ No newline at end of file +End Class diff --git a/Pilz.Simple3DFileParser/Model/Object3D.vb b/Pilz.Simple3DFileParser/Model/Object3D.vb index 52e5aa8..7e36721 100644 --- a/Pilz.Simple3DFileParser/Model/Object3D.vb +++ b/Pilz.Simple3DFileParser/Model/Object3D.vb @@ -179,22 +179,17 @@ Public Class Object3D End Function Public Sub CenterModel() - Dim avg As Vector3 = Vector3.Zero - Dim vertsCount As ULong = 0 - - For Each m As Mesh In Meshes - avg += m.GetCenterModelAvg - vertsCount += m.Vertices.Count - Next - - avg /= vertsCount - - CenterModel(avg) + Mesh.CenterModel(Meshes) End Sub - Public Sub CenterModel(avg As Vector3) - For Each m As Mesh In Meshes - m.CenterModel(avg) + + Public Shared Sub CenterModel(objs As IEnumerable(Of Object3D)) + Dim meshes As New List(Of Mesh) + + For Each obj As Object3D In objs + meshes.AddRange(obj.Meshes) Next + + Mesh.CenterModel(meshes) End Sub End Class diff --git a/Pilz.Simple3DFileParser/Other/LoaderModule.vb b/Pilz.Simple3DFileParser/Other/LoaderModule.vb index a34a287..620657f 100644 --- a/Pilz.Simple3DFileParser/Other/LoaderModule.vb +++ b/Pilz.Simple3DFileParser/Other/LoaderModule.vb @@ -69,8 +69,11 @@ Public Class File3DLoaderModule AssimpModule.AssimpLoader.LoadAssimpLibs() Dim exts As New Dictionary(Of String, String) For Each fd As Assimp.ExportFormatDescription In AssimpLibrary.Instance.GetExportFormatDescriptions - If Not exts.ContainsKey(fd.FileExtension) Then exts.Add(fd.FileExtension, fd.FormatId & " - " & fd.Description) + If Not exts.ContainsKey(fd.FileExtension) Then + exts.Add(fd.FileExtension, fd.FormatId & " - " & fd.Description) + End If Next + exts.Add("blend", "Blender") list.Add(New File3DLoaderModule("Assimp", AddressOf LoadViaAssimp, diff --git a/Pilz.Simple3DFileParser/Pilz.Simple3DFileParser.vbproj b/Pilz.Simple3DFileParser/Pilz.Simple3DFileParser.vbproj index 058d877..88d207c 100644 --- a/Pilz.Simple3DFileParser/Pilz.Simple3DFileParser.vbproj +++ b/Pilz.Simple3DFileParser/Pilz.Simple3DFileParser.vbproj @@ -52,12 +52,11 @@ ..\packages\Aspose.3D.18.4.0\lib\net40\Aspose.3D.dll - - False + ..\Shared Libs\AssimpNet.dll - ..\..\..\DLL's\ColladaSchema.dll + ..\Shared Libs\ColladaSchema.dll diff --git a/Pilz.UI/PaintingControl/DefaultDrawMethodes.vb b/Pilz.UI/PaintingControl/DefaultDrawMethodes.vb index d76539a..b802cb7 100644 --- a/Pilz.UI/PaintingControl/DefaultDrawMethodes.vb +++ b/Pilz.UI/PaintingControl/DefaultDrawMethodes.vb @@ -143,20 +143,18 @@ Public Class DefaultDrawMethodes Public Shared Sub DrawTriangle(e As PaintingObjectPaintEventArgs) Dim obj As PaintingObject = e.PaintingObject + Dim p1 As New Point(obj.Size.Width / 2 + e.X, e.Y) + Dim p2 As New Point(e.X, e.Y + obj.Size.Height) + Dim p3 As New Point(e.X + obj.Size.Width, e.Y + obj.Size.Height) + If obj.EnableFill Then Dim b As New SolidBrush(obj.FillColor) - Dim p1 As New Point(obj.Size.Width / 2 + e.X, e.Y) - Dim p2 As New Point(e.X, e.Y + obj.Size.Height) - Dim p3 As New Point(e.X + obj.Size.Width, e.Y + obj.Size.Height) e.Graphics.FillPolygon(b, {p1, p2, p3}) End If If obj.EnableOutline Then Dim lw As Single = obj.OutlineThicknes Dim p As New Pen(obj.OutlineColor, obj.OutlineThicknes) With {.DashStyle = obj.OutlineDashStyle, .Alignment = PenAlignment.Inset} - Dim p1 As New Point(obj.Size.Width / 2 + e.X, e.Y) - Dim p2 As New Point(e.X, e.Y + obj.Size.Height) - Dim p3 As New Point(e.X + obj.Size.Width, e.Y + obj.Size.Height) e.Graphics.DrawPolygon(p, {p1, p2, p3}) End If End Sub @@ -225,10 +223,10 @@ Public Class DefaultDrawMethodes End Sub Public Shared Sub DrawAreaSelection(e As PaintEventArgs, pc As PaintingControl, startMousePos As PointF, lastMousePos As PointF) - Dim p As New Pen(pc.AreaSelectionColor) - p.DashStyle = DashStyle.DashDot - p.Width = 3 Dim rectToDraw As RectangleF = HelpfulDrawingFunctions.GetRectangle(startMousePos, lastMousePos) + Dim p As New Pen(pc.AreaSelectionColor) + p.DashStyle = If(startMousePos.X >= lastMousePos.X, DashStyle.DashDot, DashStyle.Solid) + p.Width = 3 e.Graphics.DrawRectangle(p, rectToDraw.X, rectToDraw.Y, rectToDraw.Width, rectToDraw.Height) End Sub diff --git a/Pilz.UI/PaintingControl/PaintingControl.vb b/Pilz.UI/PaintingControl/PaintingControl.vb index bbc72a7..fb0f27e 100644 --- a/Pilz.UI/PaintingControl/PaintingControl.vb +++ b/Pilz.UI/PaintingControl/PaintingControl.vb @@ -23,6 +23,8 @@ Public Class PaintingControl Public Property Offset As PointF = PointF.Empty Public ReadOnly Property PaintingObjects As New PaintingObjectList(Me) + 'Public Property EnableRealTransparency As Boolean = False + Public Property VisibleForMouseEvents As Boolean = True Public Property AutoAreaSelection As Boolean = True Public Property AutoSingleSelection As Boolean = True Public Property AutoMultiselection As Boolean = True @@ -90,9 +92,10 @@ Public Class PaintingControl End Get Set(value As Color) bgColor = value - If value <> Color.Transparent Then - MyBase.BackColor = value - End If + MyBase.BackColor = value + 'If value <> Color.Transparent Then + ' MyBase.BackColor = value + 'End If End Set End Property Public ReadOnly Property IsAreaSelecting As Boolean @@ -114,6 +117,7 @@ Public Class PaintingControl End Property Public Sub New() + 'SetStyle(ControlStyles.Opaque, True) 'For real transparency DoubleBuffered = True End Sub @@ -150,7 +154,7 @@ Public Class PaintingControl curObjMouseDown = GetObjects(lastMousePos).Where(Function(n) Not n.MouseTransparency).LastOrDefault curObjMouseDown?.RaiseMouseDown(GetMouseEventArgs(e, curObjMouseDown)) - If Not GetSelectedObjects.Contains(curObjMouseDown) Then + If curObjMouseDown Is Nothing OrElse Not curObjMouseDown.Selected OrElse pressedControl Then Dim hasMovedObjects As Boolean = False If _IsMovingObjects Then For Each obj As PaintingObject In GetSelectedObjects() @@ -164,7 +168,7 @@ Public Class PaintingControl If (Not hasMovedObjects) AndAlso (Not _IsAreaSelecting) Then Dim selChanged As New List(Of PaintingObject) - If AutoRemoveSelection AndAlso Not pressedShift Then + If AutoRemoveSelection AndAlso Not pressedControl Then For Each obj As PaintingObject In PaintingObjects If obj.Selected Then obj.SelectedDirect = False @@ -175,9 +179,9 @@ Public Class PaintingControl Next End If - If AutoSingleSelection Then + If AutoSingleSelection AndAlso curObjMouseDown IsNot Nothing Then Dim objtosel As PaintingObject = curObjMouseDown - If objtosel?.EnableSelection Then + If objtosel.EnableSelection Then objtosel.SelectedDirect = Not objtosel.Selected If Not selChanged.Contains(objtosel) Then selChanged.Add(objtosel) @@ -418,7 +422,7 @@ Public Class PaintingControl Get Dim cp = MyBase.CreateParams - 'If EnableFullTransparentBackground Then + 'If EnableRealTransparency Then ' cp.ExStyle = cp.ExStyle Or &H20 'WS_EX_TRANSPARENT 'End If @@ -431,16 +435,14 @@ Public Class PaintingControl ''' ''' Protected Overrides Sub WndProc(ByRef m As Message) - Dim WM_NCHITTEST As Integer = &H84 - Dim HTTRANSPARENT As Integer = -1 + Const WM_NCHITTEST As Integer = &H84 + Const HTTRANSPARENT As Integer = -1 - 'If m.Msg = WM_NCHITTEST Then - ' m.Result = CType(HTTRANSPARENT, IntPtr) - 'Else - ' MyBase.WndProc(m) - 'End If - - MyBase.WndProc(m) + If Not VisibleForMouseEvents AndAlso m.Msg = WM_NCHITTEST Then + m.Result = CType(HTTRANSPARENT, IntPtr) + Else + MyBase.WndProc(m) + End If End Sub Protected Overrides Sub OnPaintBackground(e As PaintEventArgs) @@ -448,13 +450,13 @@ Public Class PaintingControl Me.SuspendLayout() 'Draw Background + 'If Not EnableRealTransparency Then MyBase.OnPaintBackground(e) + 'End If End Sub Protected Overrides Sub OnPaint(e As PaintEventArgs) - 'Do default Drawing Methode - MyBase.OnPaint(e) - + 'Draw PaintingObjects stuff If StopDrawing Then e.Graphics.DrawImage(bufferedImg, Point.Empty) Else @@ -482,6 +484,9 @@ Public Class PaintingControl End If End If + 'Do default Drawing Methode + MyBase.OnPaint(e) + 'Start Drawing directly to the Form ResumeLayout(False) End Sub @@ -501,53 +506,76 @@ Public Class PaintingControl Private Function CalcTextSize(obj As PaintingObject) As SizeF Return CalcTextSize(obj, Parent.CreateGraphics) End Function + Private Function CalcTextSize(obj As PaintingObject, g As Graphics) As SizeF Return g.MeasureString(obj.Text, obj.TextFont, obj.Width) End Function Private Sub SelectControlsInArea() - Dim rect As RectangleF = HelpfulDrawingFunctions.GetRectangle(startMousePos, lastMousePos) + Dim rect As RectangleF = GetRectangle(startMousePos, lastMousePos) For Each obj As PaintingObject In PaintingObjects - obj.Selected = HelpfulDrawingFunctions.OverlapsTwoRectangles(obj.Rectangle, rect) + obj.Selected = If(startMousePos.X >= lastMousePos.X, + OverlapsTwoRectangles(obj.Rectangle, rect), + RectangleContainsRectangle(rect, obj.Rectangle)) Next End Sub - Public Sub ArrangeToGrid(obj As PaintingObject) - Dim zoomedGridChunkSize As New SizeF(GridChunkSize.Width * ZoomFactor.Width, Me.GridChunkSize.Height * ZoomFactor.Height) + Public Sub ArrangeToGrid(obj As PaintingObject, snapPinnedObjects As Boolean) + If snapPinnedObjects OrElse Not IsPinnedObject(obj) Then + Dim zoomedGridChunkSize As New SizeF(GridChunkSize.Width * ZoomFactor.Width, Me.GridChunkSize.Height * ZoomFactor.Height) - Dim modTop As Integer = obj.Y Mod zoomedGridChunkSize.Height - Dim modLeft As Integer = obj.X Mod zoomedGridChunkSize.Width + Dim modTop As Integer = obj.Y Mod zoomedGridChunkSize.Height + Dim modLeft As Integer = obj.X Mod zoomedGridChunkSize.Width - Dim halfHeight As Integer = zoomedGridChunkSize.Height / 2 - Dim halfWidth As Integer = zoomedGridChunkSize.Width / 2 + Dim halfHeight As Integer = zoomedGridChunkSize.Height / 2 + Dim halfWidth As Integer = zoomedGridChunkSize.Width / 2 - If modTop > halfHeight Then - obj.Y += (zoomedGridChunkSize.Height - modTop) - Else - obj.Y -= modTop - End If + Dim zoomLocation = + Sub(obj2 As PaintingObject) + If modTop > halfHeight Then + obj2.Y += (zoomedGridChunkSize.Height - modTop) + Else + obj2.Y -= modTop + End If - If modLeft > halfWidth Then - obj.X += (zoomedGridChunkSize.Width - modLeft) - Else - obj.X -= modLeft - End If + If modLeft > halfWidth Then + obj2.X += (zoomedGridChunkSize.Width - modLeft) + Else + obj2.X -= modLeft + End If + End Sub + + zoomLocation(obj) + + For Each pinned As PaintingObject In obj.PinnedObjects + zoomLocation(pinned) + Next - If obj.EnableResize AndAlso Not obj.HardcodedSize Then Dim modH As Integer = obj.Height Mod zoomedGridChunkSize.Height Dim modW As Integer = obj.Width Mod zoomedGridChunkSize.Width - If modH > halfHeight Then - obj.Height += (zoomedGridChunkSize.Height - modH) - Else - obj.Height -= modH - End If + Dim zoomSize = + Sub(obj2 As PaintingObject) + If obj2.EnableResize AndAlso Not obj2.HardcodedSize Then + If modH > halfHeight Then + obj2.Height += (zoomedGridChunkSize.Height - modH) + Else + obj2.Height -= modH + End If - If modW > halfWidth Then - obj.Width += (zoomedGridChunkSize.Width - modW) - Else - obj.Width -= modW - End If + If modW > halfWidth Then + obj2.Width += (zoomedGridChunkSize.Width - modW) + Else + obj2.Width -= modW + End If + End If + End Sub + + zoomSize(obj) + + For Each pinned As PaintingObject In obj.PinnedObjects + zoomSize(pinned) + Next End If End Sub @@ -564,7 +592,7 @@ Public Class PaintingControl If GridEnabled Then For Each obj As PaintingObject In GetSelectedObjects() If obj.AutoAlignToGrid Then - ArrangeToGrid(obj) + ArrangeToGrid(obj, False) End If Next If Not StopDrawing Then Refresh() diff --git a/Pilz.UI/PaintingControl/PaintingObject.vb b/Pilz.UI/PaintingControl/PaintingObject.vb index 97c90d8..b2bc438 100644 --- a/Pilz.UI/PaintingControl/PaintingObject.vb +++ b/Pilz.UI/PaintingControl/PaintingObject.vb @@ -432,7 +432,7 @@ Imports Newtonsoft.Json Public Sub ArrangeToGrid() If Parent IsNot Nothing Then - Parent.ArrangeToGrid(Me) + Parent.ArrangeToGrid(Me, True) If Not Parent.StopDrawing Then Parent.Refresh() End If End Sub diff --git a/Pilz.UI/PaintingControl/PaintingObjectResizing.vb b/Pilz.UI/PaintingControl/PaintingObjectResizing.vb index 76f1b9a..9edbea5 100644 --- a/Pilz.UI/PaintingControl/PaintingObjectResizing.vb +++ b/Pilz.UI/PaintingControl/PaintingObjectResizing.vb @@ -66,7 +66,6 @@ Imports Pilz.Drawing End Sub Private Sub mControl_MouseMove(sender As Object, e As MouseEventArgs) Handles mObjControl.MouseMove - If mMouseDown AndAlso mEdge <> EdgeEnum.None Then Dim eX As Integer = e.X + mObj.Parent.Offset.X @@ -97,6 +96,8 @@ Imports Pilz.Drawing Dim eXo As Integer = e.X Dim eYo As Integer = e.Y + Dim realX As Integer = eXo + mObj.Parent.Offset.X + Dim realY As Integer = eYo + mObj.Parent.Offset.Y Dim eXwo As Integer = eXo - mObj.X Dim eYwo As Integer = eYo - mObj.Y Dim eX As Integer = eXwo + mObj.Parent.Offset.X @@ -112,7 +113,7 @@ Imports Pilz.Drawing newRect.Height = (extRect.Height - oldRect.Height) / 2 Dim setToNone As Boolean = False - Dim isOnTop As Boolean = mObj.Parent.GetObject(New PointF(eXo, eYo), True) Is mObj + Dim isOnTop As Boolean = mObj.Parent.GetObject(New PointF(realX, realY), True) Is mObj If Enabled AndAlso isOnTop Then Select Case True diff --git a/Pilz.UI/Pilz.UI.vbproj b/Pilz.UI/Pilz.UI.vbproj index 772d1bb..945ae42 100644 --- a/Pilz.UI/Pilz.UI.vbproj +++ b/Pilz.UI/Pilz.UI.vbproj @@ -68,7 +68,7 @@ - ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll diff --git a/Pilz.UI/packages.config b/Pilz.UI/packages.config index 7f83af3..93b0be8 100644 --- a/Pilz.UI/packages.config +++ b/Pilz.UI/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Pilz.Updating.Updater/App.config b/Pilz.Updating.Updater/App.config new file mode 100644 index 0000000..bc3672d --- /dev/null +++ b/Pilz.Updating.Updater/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Pilz.Updating.Updater/My Project/Application.Designer.vb b/Pilz.Updating.Updater/My Project/Application.Designer.vb new file mode 100644 index 0000000..8be2678 --- /dev/null +++ b/Pilz.Updating.Updater/My Project/Application.Designer.vb @@ -0,0 +1,38 @@ +'------------------------------------------------------------------------------ +' +' Dieser Code wurde von einem Tool generiert. +' Laufzeitversion:4.0.30319.42000 +' +' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +' der Code erneut generiert wird. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + 'HINWEIS: Diese Datei wird automatisch generiert und darf nicht direkt bearbeitet werden. Wenn Sie Änderungen vornehmen möchten + ' oder in dieser Datei Buildfehler auftreten, wechseln Sie zum Projekt-Designer. + ' (Wechseln Sie dazu zu den Projekteigenschaften, oder doppelklicken Sie auf den Knoten "Mein Projekt" im + ' Projektmappen-Explorer). Nehmen Sie auf der Registerkarte "Anwendung" entsprechende Änderungen vor. + ' + Partial Friend Class MyApplication + + _ + Public Sub New() + MyBase.New(Global.Microsoft.VisualBasic.ApplicationServices.AuthenticationMode.Windows) + Me.IsSingleInstance = false + Me.EnableVisualStyles = true + Me.SaveMySettingsOnExit = true + Me.ShutDownStyle = Global.Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses + End Sub + + _ + Protected Overrides Sub OnCreateMainForm() + Me.MainForm = Global.Pilz.Updating.UpdateInstaller.Form1 + End Sub + End Class +End Namespace diff --git a/Pilz.Updating.Updater/My Project/Application.myapp b/Pilz.Updating.Updater/My Project/Application.myapp new file mode 100644 index 0000000..1243847 --- /dev/null +++ b/Pilz.Updating.Updater/My Project/Application.myapp @@ -0,0 +1,11 @@ + + + true + Form1 + false + 0 + true + 0 + 0 + true + diff --git a/Pilz.Updating.Updater/My Project/AssemblyInfo.vb b/Pilz.Updating.Updater/My Project/AssemblyInfo.vb new file mode 100644 index 0000000..ab0119f --- /dev/null +++ b/Pilz.Updating.Updater/My Project/AssemblyInfo.vb @@ -0,0 +1,35 @@ +Imports System +Imports System.Reflection +Imports System.Runtime.InteropServices + +' Allgemeine Informationen über eine Assembly werden über die folgenden +' Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +' die einer Assembly zugeordnet sind. + +' Werte der Assemblyattribute überprüfen + + + + + + + + + + +'Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird. + + +' Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +' +' Hauptversion +' Nebenversion +' Buildnummer +' Revision +' +' Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +' übernehmen, indem Sie "*" eingeben: +' + + + diff --git a/Pilz.Updating.Updater/My Project/Resources.Designer.vb b/Pilz.Updating.Updater/My Project/Resources.Designer.vb new file mode 100644 index 0000000..315ae38 --- /dev/null +++ b/Pilz.Updating.Updater/My Project/Resources.Designer.vb @@ -0,0 +1,63 @@ +'------------------------------------------------------------------------------ +' +' Dieser Code wurde von einem Tool generiert. +' Laufzeitversion:4.0.30319.42000 +' +' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +' der Code erneut generiert wird. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + +Imports System + +Namespace My.Resources + + 'Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + '-Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + 'Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + 'mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + ''' + ''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + ''' + _ + Friend Module Resources + + Private resourceMan As Global.System.Resources.ResourceManager + + Private resourceCulture As Global.System.Globalization.CultureInfo + + ''' + ''' Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + ''' + _ + Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager + Get + If Object.ReferenceEquals(resourceMan, Nothing) Then + Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Pilz.Updating.UpdateInstaller.Resources", GetType(Resources).Assembly) + resourceMan = temp + End If + Return resourceMan + End Get + End Property + + ''' + ''' Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + ''' Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + ''' + _ + Friend Property Culture() As Global.System.Globalization.CultureInfo + Get + Return resourceCulture + End Get + Set + resourceCulture = value + End Set + End Property + End Module +End Namespace diff --git a/Pilz.Updating.Updater/My Project/Resources.resx b/Pilz.Updating.Updater/My Project/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Pilz.Updating.Updater/My Project/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Pilz.Updating.Updater/My Project/Settings.Designer.vb b/Pilz.Updating.Updater/My Project/Settings.Designer.vb new file mode 100644 index 0000000..174e4f9 --- /dev/null +++ b/Pilz.Updating.Updater/My Project/Settings.Designer.vb @@ -0,0 +1,73 @@ +'------------------------------------------------------------------------------ +' +' Dieser Code wurde von einem Tool generiert. +' Laufzeitversion:4.0.30319.42000 +' +' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +' der Code erneut generiert wird. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + _ + Partial Friend NotInheritable Class MySettings + Inherits Global.System.Configuration.ApplicationSettingsBase + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings) + +#Region "Automatische My.Settings-Speicherfunktion" +#If _MyType = "WindowsForms" Then + Private Shared addedHandler As Boolean + + Private Shared addedHandlerLockObject As New Object + + _ + Private Shared Sub AutoSaveSettings(sender As Global.System.Object, e As Global.System.EventArgs) + If My.Application.SaveMySettingsOnExit Then + My.Settings.Save() + End If + End Sub +#End If +#End Region + + Public Shared ReadOnly Property [Default]() As MySettings + Get + +#If _MyType = "WindowsForms" Then + If Not addedHandler Then + SyncLock addedHandlerLockObject + If Not addedHandler Then + AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings + addedHandler = True + End If + End SyncLock + End If +#End If + Return defaultInstance + End Get + End Property + End Class +End Namespace + +Namespace My + + _ + Friend Module MySettingsProperty + + _ + Friend ReadOnly Property Settings() As Global.Pilz.Updating.UpdateInstaller.My.MySettings + Get + Return Global.Pilz.Updating.UpdateInstaller.My.MySettings.Default + End Get + End Property + End Module +End Namespace diff --git a/Pilz.Updating.Updater/My Project/Settings.settings b/Pilz.Updating.Updater/My Project/Settings.settings new file mode 100644 index 0000000..85b890b --- /dev/null +++ b/Pilz.Updating.Updater/My Project/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Pilz.Updating.Updater/Pilz.Updating.UpdateInstaller.vbproj b/Pilz.Updating.Updater/Pilz.Updating.UpdateInstaller.vbproj new file mode 100644 index 0000000..30ba063 --- /dev/null +++ b/Pilz.Updating.Updater/Pilz.Updating.UpdateInstaller.vbproj @@ -0,0 +1,136 @@ + + + + + Debug + AnyCPU + {1BA3D8E8-C514-4182-9E6E-9E6BB7AF0403} + WinExe + Pilz.Updating.UpdateInstaller.My.MyApplication + Pilz.Updating.UpdateInstaller + Pilz.Updating.UpdateInstaller + 512 + WindowsForms + v4.5 + true + + + AnyCPU + true + full + true + true + bin\Debug\ + Pilz.Updating.UpdateInstaller.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + AnyCPU + pdbonly + false + true + true + bin\Release\ + Pilz.Updating.UpdateInstaller.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + On + + + Binary + + + Off + + + On + + + + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + Form + + + UpdateInstaller.vb + Form + + + + True + Application.myapp + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + UpdateInstaller.vb + + + VbMyResourcesResXFileCodeGenerator + Resources.Designer.vb + My.Resources + Designer + + + + + MyApplicationCodeGenerator + Application.Designer.vb + + + SettingsSingleFileGenerator + My + Settings.Designer.vb + + + + + + + {354255d9-9536-4400-b915-ffc49c2ce93f} + Pilz.Updating + + + {277d2b83-7613-4c49-9cab-e080195a6e0c} + Pilz + + + + \ No newline at end of file diff --git a/Pilz.Updating.Updater/UpdateInstaller.Designer.vb b/Pilz.Updating.Updater/UpdateInstaller.Designer.vb new file mode 100644 index 0000000..154fd55 --- /dev/null +++ b/Pilz.Updating.Updater/UpdateInstaller.Designer.vb @@ -0,0 +1,65 @@ + _ +Partial Class UpdateInstaller + Inherits System.Windows.Forms.Form + + 'Das Formular überschreibt den Löschvorgang, um die Komponentenliste zu bereinigen. + _ + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + Try + If disposing AndAlso components IsNot Nothing Then + components.Dispose() + End If + Finally + MyBase.Dispose(disposing) + End Try + End Sub + + 'Wird vom Windows Form-Designer benötigt. + Private components As System.ComponentModel.IContainer + + 'Hinweis: Die folgende Prozedur ist für den Windows Form-Designer erforderlich. + 'Das Bearbeiten ist mit dem Windows Form-Designer möglich. + 'Das Bearbeiten mit dem Code-Editor ist nicht möglich. + _ + Private Sub InitializeComponent() + Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(UpdateInstaller)) + Me.ProgressBar1 = New System.Windows.Forms.ProgressBar() + Me.Label1 = New System.Windows.Forms.Label() + Me.SuspendLayout() + ' + 'ProgressBar1 + ' + Me.ProgressBar1.Location = New System.Drawing.Point(15, 25) + Me.ProgressBar1.Name = "ProgressBar1" + Me.ProgressBar1.Size = New System.Drawing.Size(390, 16) + Me.ProgressBar1.TabIndex = 0 + ' + 'Label1 + ' + Me.Label1.AutoSize = True + Me.Label1.Location = New System.Drawing.Point(12, 9) + Me.Label1.Name = "Label1" + Me.Label1.Size = New System.Drawing.Size(62, 13) + Me.Label1.TabIndex = 1 + Me.Label1.Text = "Updating ..." + ' + 'Form1 + ' + Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) + Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font + Me.ClientSize = New System.Drawing.Size(417, 55) + Me.ControlBox = False + Me.Controls.Add(Me.Label1) + Me.Controls.Add(Me.ProgressBar1) + Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon) + Me.Name = "Form1" + Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen + Me.Text = "Updater" + Me.ResumeLayout(False) + Me.PerformLayout() + + End Sub + + Friend WithEvents ProgressBar1 As ProgressBar + Friend WithEvents Label1 As Label +End Class diff --git a/Pilz.Updating.Updater/UpdateInstaller.resx b/Pilz.Updating.Updater/UpdateInstaller.resx new file mode 100644 index 0000000..7c83c6d --- /dev/null +++ b/Pilz.Updating.Updater/UpdateInstaller.resx @@ -0,0 +1,643 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAkAICAQAAEABADoAgAAlgAAABAQEAABAAQAKAEAAH4DAAAwMAAAAQAIAKgOAACmBAAAICAAAAEA + CACoCAAAThMAABAQAAABAAgAaAUAAPYbAAAAAAAAAQAgAEIdAABeIQAAMDAAAAEAIACoJQAAoD4AACAg + AAABACAAqBAAAEhkAAAQEAAAAQAgAGgEAADwdAAAKAAAACAAAABAAAAAAQAEAAAAAACAAgAAAAAAAAAA + AAAQAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8A + AAD/AP8A//8AAP///wAAAAAAAAAAAAAAAAAAAAAAAAiIiIiIiIiIiIiIiIgAAACHd3d3d3d3d3d3d3d3 + gAAAh3d3d3d3d3d3d3d3d4AAAId3d3d3d3d3d3d3d3iAAACHd3d3d3d3d3d3d3d3gAAAh3d3d3d3d3d3 + d3d3d4AAAIh4eHh3h3h3h3h3h3iAAACIeHh3h4eHh4eHh4eIgAAAiHd3d4eHh4eHh4eHh4AAAIiId0Z3 + h4h4d4h4d4iAAACId3Z2d4eHiIiHiIiHgAAAiHZ2ZnZ4h4eHh4eHiIAAAIh3ZnZ2d4iIiIiIiIiAAACI + d3Z2Z3eIiIiIiIiIgAAAiIh2xneIiIiIiIiIiIAAAIh4dnZniIiIiIiIiIiAAACIiHZ8d4iIiIiIiIiI + gAAACIhnZneIiIiIiIiIiIAAAAh3dmdnh4iIeHh4eHgAAAAIh3Z8Z4iIiHh4eHiIAAAACIh2dneHiIiI + iIiIiAAAAACIdnZniIiIiIiIiIAAAAAAiHZnx3iIiIiIiIiAAAAAAAiHZ2dniIiIiIiIAAAAAAAAB2dn + ZnZ2dnZ2doAAAAAAAABnx2dnZ2dmdsaAAAAAAAAAB2dnxnxnZ2dngAAAAAAAAAB2dnZ2fGfHZoAAAAAA + AAAACHZ2dnZ2ZmeAAAAAAAAAAAAAAAAIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAP/////gAAAPwAAAB8AA + AAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB+AA + AAfgAAAP4AAAD+AAAA/wAAAf8AAAH/gAAD/+AAAf/wAAH/+AAB//wAAf/+AAH///4P//////KAAAABAA + AAAgAAAAAQAEAAAAAADAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICA + AACAgIAAwMDAAAAA/wAA/wAAAP//AP8AAAD/AP8A//8AAP///wAAAAAAAAAAAAh3d3d3d3cACHd3d3d3 + dwAId3h3d3d4AAiHd4eHh3gACHdnh4d4eAAIdmd4iIiIAAh3Z3iIiIgACIdniIiIiAAId2eIh4eIAACH + d3iIiIgAAIdmiIiIgAAACHZ3d3dwAAAAdnZ2Z2AAAAAIZ2dnYAAAAAAAAAAAAP////+AA///gAP//4AD + //+AA///gAP//4AD//+AA///gAP//4AD///AA///wAf//+AH///wB///+Af///////8oAAAAMAAAAGAA + AAABAAgAAAAAAIAKAAAAAAAAAAAAAAABAAAAAAAAAAAAAJ5gLgCbYjEAnWMyAJpjNACbZDUAnGQ1AJ1n + OQChYi8Ao2MwAKJkMQClZDAAomY0AKVnNACoZjEApmg1AKpoMgCtaTMAqWk1AK5qNAClaTkApWs8AKZs + PACtbDgAqW09ALBqNACybDUAtW01ALhvNwCwbTgArnA+ALlwNwC2cDoAsnE/ALtxOAC9cjgAwHM5AMF0 + OQDEdjsAxXc8AJxqQAClbUAAs3JAALRzQQC1dkUAvXlFALJ5TQC0e08AsHpQAI1+bQCRf20Ax3tBAMh/ + RgC6hl0AvoleAJOAbgCKg3gAjIN4AI6FegCVgnAAl4RxAJmFcgCRiHwAmYx+AKCCZwCogmQAoYNoAKOE + aAClhWkAqYdqAK2JawCsiWwAsYVjALCGZADHgEoAz4xaAMCKYADJlm4AzJdvAM2YbwDSlGUAyZlyAM+Z + cADKmnQA0JlwANKddADWnnQA1aB4ANejfABokKkAapKsAGyUrQBvl7AAcZmyAHOatAB0nLYAfZ+zAHqf + tgB3nrgAeJ+5AH2gtQB5oLoAfqK4AHuivAB8o70AfaS+AH6lwACVjoQAkY+IAJyTigCNkZQAlpaSAJGU + mACVmpsAkpmdAJacnQCYn58AnJ+fAKmWhQCim5IAvaKLAImYpACPnKgAkZ6qAI+iqwCaoKAAkaKsAJOl + rQCVpq8Am6etAIGjtwCOpbIAgaS5AIWmuwCCprwAhai9AImqvgCRpbAAlKazAJaosACZqrIAn6uxAJOt + vwDbqYMA3K6LANWwkwDftpcAgKfBAIOnxACBqMIAhqnBAIOqxACEqMUAhazGAIiswgCJr8cAh6vIAIau + yACJq8gAia7KAImwygCKsswAjLHMAI20zgCbtMMAkbHKAJK0ywCTs8wAlLPNAJO0zgCUtM4Am7jNAJy5 + zgCPt9AAkLbQAJa20ACRudIAlbrSAJS81ACYudIAnbrQAJi80wCfvNEAmr3VAJ2/1ACgvdIAnMDWAJvB + 2ACgwdYAocPYAKXD2ACuyNsArczfALPL3QC1z98AuMzcALTQ4QC40uEAwdPiAMDW5QDL2eIAyd3pAP9R + xwD/cdEA/5HcAP+x5QD/0fAA////AAAAAAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx + /wD0Uf8A9nH/APeR/wD5sf8A+9H/AP///wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR + /wCmMf8AtFH/AMJx/wDPkf8A3LH/AOvR/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA + 8AA+Ef8AWDH/AHFR/wCMcf8AppH/AL+x/wDa0f8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAC0rKysrKysrKysrKysq6usrKysq6urq6urq6urq6urq6urrKurq8MAAAAAAAAA + AABeWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZW6sAAAAAAAAAAABfWVlZWVlZWVlZ + WVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWqsAAAAAAAAAAABfW1tbW1tbW1tbW1tbW1tbW1tbW1tb + W1tbW1tbW1tbW1tbW1taW6wAAAAAAAAAAABfW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tb + W1tbXKwAAAAAAAAAAABiXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXawAAAAAAAAA + AABlXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXqwAAAAAAAAAAABlXl9eXl5eXl5e + X15fXl5eXl9eX19fX19fX19fX19fX15fXl9fX6wAAAAAAAAAAABnYmJiYmJiYmJfYl9iYmJiYmJfYl9i + X2JfYl9iX2JfYl9iX2JfYrQAAAAAAAAAAABnY2NjYmNjY2NjY2NjY2NjY2NjZWVlZWVlZWVlZWVlY2Nj + ZWNjZbQAAAAAAAAAAABpZWdlZ2VlZ2FlZWdlZWdlZ2VlZWVlZWVlZWVlZWVlZ2VlZWdlZbQAAAAAAAAA + AABpaGhoaGhoYDE4ZGhoaGhoaGhpaGhoaGhoaGhoaGhoaGhoaGhoaLQAAAAAAAAAAABqaWlqaWlkMgIF + OWZpaWpqaWpqampqampqampqampqampqamlpabYAAAAAAAAAAACTk5OTk4IyAwEBBTqGk5OTk5OTk5OT + k5OTk5OTk5OTk5OTk5OTk7QAAAAAAAAAAACVlZeVhDcDCAEBAQU6hpWVl5WVlZWVlZWVlZWVlZWVl5WX + l5WVlbQAAAAAAAAAAACVl5eFOwwICAgIAQEFPoeXmZeXl5eXl5eXl5eXl5eXl5eXl5eXl7YAAAAAAAAA + AACVnYc9DAgJCAgICAEIBj6amZ2dnZ2dnZ2dnZ2dnZ2dmZ2ZnZ2ZmbYAAAAAAAAAAACXiD0PCwsKCQgJ + CAgBAQY+mpudm5ubm5udm52bnZudm6CdoJ2bnbYAAAAAAAAAAACWPykVFAsLCwoJCggIBgcobJugoKGg + oKGgoaChoKGgoaChoaChn7kAAAAAAAAAAACWiX5+bxULCwsKCgkKa3x8g6Kjo6OjoaOho6GjoaOhoaGj + oaOhoLkAAAAAAAAAAACdo6OjfxYODg4LCwoMcaOjraOjo6Ojo6Ojo6Ojo6Oto6Ojo62jobkAAAAAAAAA + AACdra2tgBgSDg4LCwsMc62tra2xsbWxra2tra2wrbCtra2wrbCto7kAAAAAAAAAAACfsLCwixgQEBAO + DgsNc7CtsLrFxcXFu7CwrbCtsK2wsLCwsLCwrbkAAAAAAAAAAACfsLKyjB4SEBAQDg4PdLKwsrvExMXE + u7KysrKysrKysrCysrCyrbkAAAAAAAAAAAChsrKyjB4TEREREBISfbKysrvAwMDAu7KysrKysrKysrKy + srKysrkAAAAAAAAAAACdo62jih4TExMRERASc62to7G9vr29saOto62tra2tra6jraOuobkAAAAAAAAA + AACYampqeR4aGRkTEREXbmqTk5inqKinlJRqampqampqamqUampqarkAAAAAAAAAAAC0mJiceiEaGhoZ + GRMXcJiYmJ6or6qonpyYnJicmJyYnJicmJicmAAAAAAAAAAAAADGnJyceysbGxoaGhkXcpycnJ+qr6+q + opycnJycnJycnJycnJycpwAAAAAAAAAAAAAAqZ+ffiscHBsbGhodcZ+fn6Kzs6+vop+fn5+fn5+fn5+f + n5+fwQAAAAAAAAAAAAAAv6KiiiwcHBwbGxoabaKioqmzs7Ozo6KioqKioqKioqOioqKjAAAAAAAAAAAA + AAAAAKOuji8fHxwcHBsbQaWjo663t7e3rq6jrqOuo66jrqOuo66+AAAAAAAAAAAAAAAAAL2tpkgjIiIf + HBwcKnWusLC3t7q3sq2wrbCtsK2wra2wra0AAAAAAAAAAAAAAAAAAMewsHYkIyIiIh8cHDCBsLK8urq7 + srGwsrCysLCysLKwsLoAAAAAAAAAAAAAAAAAAAC6so0tJCQjIiIiHBwud6S8uLy8tbKxsbGxsbGxsbGx + scIAAAAAAAAAAAAAAAAAAAAAychTJSQkJCMiHx8fIC5JRkZHRUVFRERERENDQ0NCQHgAAAAAAAAAAAAA + AAAAAAAAAAAASiUlJCQjIyIfHxwcHBsbGhoaGRMTEREQEBAODjUAAAAAAAAAAAAAAAAAAAAAAAAAkicm + JSUkIyMjIh8cHBsbGxoaGhkTExEREBAQEDUAAAAAAAAAAAAAAAAAAAAAAAAAAFgmJiYlJSQkIyIiHxwc + HBsbGhoaGhMTEREREDUAAAAAAAAAAAAAAAAAAAAAAAAAAABWJyYmJSUkJCMjIh8fHBwbGxsaGhoZExMR + ETYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjzMnJiYlJSQkIyMiIh8cHBsbGhoaGRkTETYAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABLJyYmJiUkJCQjIyIiHBwcGxsaGhoZGUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAFA0JiYlJSQkIyMiHx8cHBsbGxoaGUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJBYV1dX + VVRST09PTk5NTU1NUZEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP// + /////wAA////////AADwAAAAAB8AAPAAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAAAAAAHwAA8AAAAAAf + AADwAAAAAB8AAPAAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA + AAAAHwAA8AAAAAAfAADwAAAAAB8AAPAAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAAAAAAHwAA8AAAAAAf + AADwAAAAAB8AAPAAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAAAAAAHwAA8AAAAAAfAADwAAAAAD8AAPAA + AAAAPwAA+AAAAAA/AAD4AAAAAH8AAPwAAAAAfwAA/AAAAAD/AAD8AAAAAP8AAP4AAAAA/wAA/wAAAAD/ + AAD/4AAAAP8AAP/gAAAA/wAA//AAAAD/AAD/+AAAAP8AAP/8AAAA/wAA//8AAAD/AAD//8AAAP8AAP// + +AAA/wAA////////AAD///////8AACgAAAAgAAAAQAAAAAEACAAAAAAAgAQAAAAAAAAAAAAAAAEAAAAA + AAAAAAAAnmEuAJtjNACcYzUAnWQ1AJtoPgCdaj8AoWIvAKNjMACjZDAApWQwAKhmMQCqaDIArWkzAK9q + NACkajsApWs8AKZtPQCpbj4AsGs0ALJsNQC1bTUAuG83AK1wPwC5cDcAtnA6ALZxPAC6cTgAvXI4AL91 + PADAczkAwXQ6AMR2OwDFdzwAl2pDAJtrQgCgbEAAqW9AAK1xQAChdE4AsnJBALRzQQC0dkYArXpTALR8 + UADGe0IAyX9IAJmCbACLgnYAjoV5AJGHfACZhngAmYl6AJyLfQCdjX0Aq4hrALCJagCiiHMApY98AMiA + SgDOi1gAzoxZAM6SZABpkasAa5OtAGyUrQB/l6MAbpawAHCYsQBzm7QAdJy1AHuftQB3n7gAeqG6AH6i + uAB8pL0Af6fBAIeOjgCRkIoAipCQAI2TkgCQlZUAlZqaALCnnQCPm6EAjJ2rAJChrwCPo7AAj6WxAI6o + tgCBpbsAgKe/AISovgCNqboAkaaxAJKmtQCTqLMAlqq1AJirtQCZrLYAkq2/AJituACfr7gAo6alAKOw + twCjsrkAzaiLANCqjADNrJEA37OSANq1mQDct5oAg6fEAICowQCHq8EAg6vEAISpxACFrcYAia/HAIat + yACIrcoAjK3JAJOuwQCJsMoAjLLKAIuxzACPscwAjrbPAJS0ygCRtc4AlbXOAJm3zwCOtdAAk7fQAJa3 + 0ACRuNIAlbnSAJO71ACZudEAmbzUAJ2+1ACdwNcAosTaAKTF2gCtyt0AuMzaALrO3AC80N4AsM3gALbR + 4QC90eAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD///8AAAAAAC8DAABQBAAAcAYAAJAJ + AACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/1NEA////AAAAAAAvAA4AUAAXAHAA + IQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/scgA/9HfAP///wAAAAAALwAgAFAA + NgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/kdwA/7HlAP/R8AD///8AAAAAACwA + LwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2cf8A95H/APmx/wD70f8A////AAAA + AAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0Uf8AwnH/AM+R/wDcsf8A69H/AP// + /wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBYMf8AcVH/AIxx/wCmkf8Av7H/ANrR + /wD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACRkZGRkZGRkZGRkZGRkZGRkZGR + kZGRkZGRAAAAAAAAkUE/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/P0CRAAAAAACSQT8/P0A/QD8/Pz9APz8/ + Pz8/Pz8/Pz9AQZEAAAAAAJFDQUNBQ0FDQ0NBQ0NDQ0NDQ0NDQ0NDQUNDkgAAAAAAkUVERERERERERERE + REREREREREREREREREWSAAAAAACSRkVGRUVFRkZFRUVGRkZGRkZGRkVGRUZGRpIAAAAAAJJISEhISEhI + SEhISEhISEhISEhISEhISEhIkgAAAAAAkktLSUlJQkdLSUtJS0lLSUlJS0lLSUtJS0mSAAAAAACTS0tL + S00iMEpLW0tLTEtMS0xLW0tMS0xLS5MAAAAAAJNMcVtPBQECMVpxcXFxcXFxcXFxcXFxcXFMkgAAAAAA + k3NzUAYHAQEDMlxzc3N1c3N1c3Nzc3Nzc3OTAAAAAACTc1EkCAkHBwcEMnJ3dXZ1dnV2dXZ1dnZ3dZMA + AAAAAJNUJxAKCQgJBwQjTnZ7e3t7e317e317e3t2lgAAAAAAk11eUhAKCgkJL1hZfH99fX1/fX1/fX1/ + fH2WAAAAAACWfX9gJQsLCgk0f4SHiIiHf39/f39/f39/fZYAAAAAAJZ/h2ElDAwLCjaHiY+VlY+Hh4eH + h4eHh4mElgAAAAAAloeJZSYODAwMNomJj5SUj4mJiYmJiYmJiYeWAAAAAAAAeHtXJg4NDQ00e3uFjIyF + e3t7e3t7e3t7d5MAAAAAAAB0cFUmFBMODTNwcHmCgnlwcHBwcHBwcHB0AAAAAAAAAIp4VigVFRQTNXh4 + foaGfnh4eXh4eHh4eIMAAAAAAAAAln1fKhYVFRU5fH2BioiFfX19fX19fX19lgAAAAAAAAAAiHosGxgW + FSt6hIiLi4iEhISEhISEhIgAAAAAAAAAAACQhTgcGxgWGTqAi42Ni4mIh4mHiIeIkAAAAAAAAAAAAACO + Ux0eHBsYGjdnaGlmY2NjY2NiYmEAAAAAAAAAAAAAAAAAPh8eHBwbGBopKSgmFxcXEhIREWwAAAAAAAAA + AAAAAAAAOyAfHhwcGxYWFRUUFA4NDQwMagAAAAAAAAAAAAAAAAAALiAfHx4cGxsWFRUUFBQODQ1rAAAA + AAAAAAAAAAAAAAAAPCEgHx4eHBsYFhUVFBMTDWsAAAAAAAAAAAAAAAAAAAAAbT0tHx8eHBwbGBYVFRQT + awAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG9vbm5uAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAP/////gAAAPwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AA + AAfAAAAHwAAAB8AAAAfAAAAHwAAAB+AAAAfgAAAP4AAAD+AAAA/wAAAf8AAAH/gAAD/+AAAf/wAAH/+A + AB//wAAf/+AAH///4P//////KAAAABAAAAAgAAAAAQAIAAAAAABAAQAAAAAAAAAAAAAAAQAAAAAAAAAA + AACcZDUAnWc5AKFiLwCjZTIApWUwAKlnMgCuajMArGs2AKVtPwCxazQAtW01ALlwNwC1cDoAs3I+ALpx + OQC+cjkAu3M8AL52PgDAdDkAl3RWAJ52VACpcUMArXJDALF1RQC0ek0AontbAKd8WwChfF0AtH5UAJp/ + ZwDCeUEAjoR4AKyOdQChjXoApI57AKmSfQDJg08A0ZZpAG6VrQBvl7AAc5qyAHSasgB1nbYAeZ+4AHyg + tgB7o7wAfqW9AIaKiACQj4oAgJmoAIafrQCUoKQAmaSqAI2isgCCprwAkaa1AJCptgCVrboAy6iMANur + hgCBqcIAh67GAIiqwwCMq8QAhq3IAImuyQCNtM0AkrbOAJW2zwCZtskAnLnMAJ+8zwCQttAAkbjRAJi7 + 0gCYvNQAornJAKi7yACiv9IAoL3UAKnC0QCnx9sAqsfaAK3H2QAKsAAAC88AAA7wAAAg/xIAPf8xAFv/ + UQB5/3EAmP+RALX/sQDU/9EA////AAAAAAAULwAAIlAAADBwAAA9kAAATLAAAFnPAABn8AAAeP8RAIr/ + MQCc/1EArv9xAMD/kQDS/7EA5P/RAP///wAAAAAAJi8AAEBQAABacAAAdJAAAI6wAACpzwAAwvAAANH/ + EQDY/zEA3v9RAOP/cQDp/5EA7/+xAPb/0QD///8AAAAAAC8mAABQQQAAcFsAAJB0AACwjgAAz6kAAPDD + AAD/0hEA/9gxAP/dUQD/5HEA/+qRAP/wsQD/9tEA////AAAAAAAvFAAAUCIAAHAwAACQPgAAsE0AAM9b + AADwaQAA/3kRAP+KMQD/nVEA/69xAP/BkQD/0rEA/+XRAP///wAAAAAALwMAAFAEAABwBgAAkAkAALAK + AADPDAAA8A4AAP8gEgD/PjEA/1xRAP96cQD/l5EA/7axAP/U0QD///8AAAAAAC8ADgBQABcAcAAhAJAA + KwCwADYAzwBAAPAASQD/EVoA/zFwAP9RhgD/cZwA/5GyAP+xyAD/0d8A////AAAAAAAvACAAUAA2AHAA + TACQAGIAsAB4AM8AjgDwAKQA/xGzAP8xvgD/UccA/3HRAP+R3AD/seUA/9HwAP///wAAAAAALAAvAEsA + UABpAHAAhwCQAKUAsADEAM8A4QDwAPAR/wDyMf8A9FH/APZx/wD3kf8A+bH/APvR/wD///8AAAAAABsA + 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 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAH9//wJ/n78If5+/CH+fvwh/n78If5+/CH+fvwh/n78If5+/CH+fvwh/n78I + f5+/CH+fvwh/n78If5+/CH+fvwh/n78If5+/CH+fvwh/n78If5+/CH+fvwh/n78If5+/CH+fvwh/n78I + f5+/CH+fvwh/n78If5+/CH+fvwh/n78If5+/CH+fvwh/n78If5+/CH+fvwh/n78If5+/CH+qqgYAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHWcujR1nbuydZ26t3Wdurd1nbq3dZ26t3Wdurd1nbq3 + dZ26t3Wdurd1nbq3dZ26t3Wdurd1nbq3dZ26t3Wdurd1nbq3dZ26t3Wdurd1nbq3dZ26t3Wdurd1nbq3 + dZ26t3Wdurd1nbq3dZ26t3Wdurd1nbq3dZ26t3Wdurd1nbq3dZ26t3Wdurd1nbq3dZ26t3Wdurd1nbq3 + dZ26t3eevYR/qqoGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0hvl7P3aJCq/2iQqv9okKr/ + aJCq/2iQqv9okKr/aJCq/2iQqv9okKr/aJCq/2iQqv9okKr/aJCq/2iQqv9okKr/aJCq/2iQqv9okKr/ + aJCq/2iQqv9okKr/aJCq/2iQqv9okKr/aJCq/2iQqv9okKr/aJCq/2iQqv9okKr/aJCq/2iQqv9okKr/ + aJCq/2iQqv9okKr/apKt/3Wdurd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0hvl7P3 + aJCp/2iQqf9okKn/aJCp/2iQqf9okKn/aJCp/2iQqf9okKn/aJCp/2iQqf9okKn/aJCp/2iQqf9okKn/ + aJCp/2iQqf9okKn/aJCp/2iQqf9okKn/aJCp/2iQqf9okKn/aJCp/2iQqf9okKn/aJCp/2iQqf9okKn/ + aJCp/2iQqf9okKn/aJCp/2iQqf9okKn/apKs/3Wdurd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAHifu0hxmbT3a5Os/2uTrP9rk6z/a5Os/2uTrP9rk6z/a5Os/2uTrP9rk6z/a5Os/2uTrP9rk6z/ + a5Os/2uTrP9rk6z/a5Os/2uTrP9rk6z/a5Os/2uTrP9rk6z/a5Os/2uTrP9rk6z/a5Os/2uTrP9rk6z/ + a5Os/2uTrP9rk6z/a5Os/2uTrP9rk6z/a5Os/2uTrP9rk6z/bZWu/3adurd/n78IAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHifu0hxmbX3bJSt/2yUrf9slK3/bJSt/2yUrf9slK3/bJSt/2yUrf9slK3/ + bJSt/2yUrf9slK3/bJSt/2yUrf9slK3/bJSt/2yUrf9slK3/bJSt/2yUrf9slK3/bJSt/2yUrf9slK3/ + bJSt/2yUrf9slK3/bJSt/2yUrf9slK3/bJSt/2yUrf9slK3/bJSt/2yUrf9slK3/bpav/3aeurd/n78I + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0hzm7b3b5ew/2+XsP9vl7D/b5ew/2+XsP9vl7D/ + b5ew/2+XsP9vl7D/b5ew/2+XsP9vl7D/b5ew/2+XsP9vl7D/b5ew/2+XsP9vl7D/b5ew/2+XsP9vl7D/ + b5ew/2+XsP9vl7D/b5ew/2+XsP9vl7D/b5ew/2+XsP9vl7D/b5ew/2+XsP9vl7D/b5ew/2+XsP9vl7D/ + cJiy/3aevLd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0h0nLf3cZmy/3GZsv9xmbL/ + cZmy/3GZsv9xmbL/cZmy/3GZsv9xmbL/cZmy/3GZsv9xmbL/cZmy/3GZsv9xmbL/cZmy/3GZsv9xmbL/ + cZmy/3GZsv9xmbL/cZmy/3GZsv9xmbL/cZmy/3GZsv9xmbL/cZmy/3GZsv9xmbL/cZmy/3GZsv9xmbL/ + cZmy/3GZsv9xmbL/cpqz/3aevLd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0h1nbj3 + c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/ + c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/ + c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/dJy1/3eevLd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAHifu0h2nrn3dZ22/3Wdtv91nbb/dZ22/3Wdtv91nbb/dZ22/3Wdtv91nbb/dZ22/3Wdtv91nbb/ + dZ22/3Wdtv91nbb/dZ22/3Wdtv91nbb/dZ22/3Wdtv91nbb/dZ22/3Wdtv91nbb/dZ22/3Wdtv91nbb/ + dZ22/3Wdtv91nbb/dZ22/3Wdtv91nbb/dZ22/3Wdtv91nbb/dZ23/3egvbd/n78IAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHifu0h3oLr3d5+4/3efuP93n7j/d5+4/3efuP93n7j/d5+4/3efuP93n7j/ + d5+4/3efuP93n7j/d5+4/3efuP93n7j/d5+4/3efuP93n7j/d5+4/3efuP93n7j/d5+4/3efuP93n7j/ + d5+4/3efuP93n7j/d5+4/3efuP93n7j/d5+4/3efuP93n7j/d5+4/3efuP93n7j/d5+5/3egvbd/n78I + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0h4obv3eaG6/3mhuv95obr/eaG6/3mhuv95obr/ + eaG6/3qftv96n7f/eaG6/3mhuv95obr/eaG6/3mhuv95obr/eaG6/3mhuv95obr/eaG6/3mhuv95obr/ + eaG6/3mhuv95obr/eaG6/3mhuv95obr/eaG6/3mhuv95obr/eaG6/3mhuv95obr/eaG6/3mhuv95obr/ + eaG7/3egvbd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0h5orz3e6O8/3ujvP97o7z/ + e6O8/3ujvP97o7z/fZ+z/4x+b/+Kg3j/fKC2/3ujvP97o7z/e6O8/3ujvP97o7z/e6O8/3ujvP97o7z/ + e6O8/3ujvP97o7z/e6O8/3ujvP97o7z/e6O8/3ujvP97o7z/e6O8/3ujvP97o7z/e6O8/3ujvP97o7z/ + e6O8/3ujvP97o7z/e6O8/3mgvbd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0h6o733 + faW+/32lvv99pb7/faW+/32lvv9/obX/j35s/5tiMf+aYzT/jIN4/36iuP99pb7/faW+/32lvv99pb7/ + faW+/32lvv99pb7/faW+/32lvv99pb7/faW+/32lvv99pb7/faW+/32lvv99pb7/faW+/32lvv99pb7/ + faW+/32lvv99pb7/faW+/32lvv99pb7/fKS+/3mhvrd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAHifu0h7pL73f6fA/3+nwP9/p8D/f6fA/4Gjt/+Rf23/nWMy/51gLv+cYC3/m2M0/42Eef+ApLr/ + f6fA/3+nwP9/p8D/f6fA/3+nwP9/p8D/f6fA/3+nwP9/p8D/f6fA/3+nwP9/p8D/f6fA/3+nwP9/p8D/ + f6fA/3+nwP9/p8D/f6fA/3+nwP9/p8D/f6fA/3+nwP9/p8D/fqbA/3mhvrd/n78IAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHifu0h8pcD3ganC/4Gpwv+BqcL/g6W5/5OAbv+eYzP/n2Eu/55hLv+eYC7/ + nWAu/5tkNf+Ohnr/gqa8/4Gpwv+BqcL/ganC/4Gpwv+BqcL/ganC/4Gpwv+BqcL/ganC/4Gpwv+BqcL/ + ganC/4Gpwv+BqcL/ganC/4Gpwv+BqcL/ganC/4Gpwv+BqcL/ganC/4Gpwv+BqcL/gKjC/3mhvrd/n78I + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0h9psH3g6vE/4OrxP+Fprv/lYJw/6BlM/+hYi// + oGIv/59hLv+fYS7/nmEu/51gLv+cZDX/j4d7/4Sovv+Dq8T/g6vE/4OrxP+Dq8T/g6vE/4OrxP+Dq8T/ + g6vE/4OrxP+Dq8T/g6vE/4OrxP+Dq8T/g6vE/4OrxP+Dq8T/g6vE/4OrxP+Dq8T/g6vE/4OrxP+Dq8T/ + gqrD/3qhvrd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0h+p8L3ha3G/4epvP+XhHH/ + omY0/6JjL/+iYy//oWIv/6BiL/+gYi//n2Eu/55hLv+eYS7/nGQ1/5GIfP+GqsD/ha3G/4Wtxv+Frcb/ + ha3G/4Wtxv+Frcb/ha3G/4Wtxv+Frcb/ha3G/4Wtxv+Frcb/ha3G/4Wtxv+Frcb/ha3G/4Wtxv+Frcb/ + ha3G/4Wtxv+Frcb/hKzF/3qjwLd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0iAqMP3 + iaq+/5mFcv+lZzX/pWQw/6RkMP+jZDD/omMv/6JjL/+hYi//oGIv/59iL/+fYS7/nmEu/5xkNf+SiX3/ + iKzC/4evyP+Hr8j/h6/I/4evyP+Hr8j/h6/I/4evyP+Hr8j/h6/I/4evyP+Hr8j/h6/I/4evyP+Hr8j/ + h6/I/4evyP+Hr8j/h6/I/4evyP+Hr8j/ha3H/3qjwLd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAHifu0iCpr33mYx+/6VtQP+lazz/pWk5/6VlMf+lZDD/pGQw/6NjMP+iYy//oWMv/6FiL/+gYi// + nmU1/51nOf+cakD/kY+I/4mvx/+Jscr/ibHK/4mxyv+Jscr/ibHK/4mxyv+Jscr/ibHK/4mxyv+Jscr/ + ibHK/4mxyv+Jscr/ibHK/4mxyv+Jscr/ibHK/4mxyv+Jscr/h6/J/3qjwLd/n78IAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHifu0iDp8H3kaWw/5GjrP+Ro6z/lpaS/6VqOv+mZTH/pWUw/6RkMP+jZDD/ + o2Mw/6JjL/+hZDL/lY6E/4+iq/+Poqv/jqWy/4uxyf+Ls8z/i7PM/4uzzP+Ls8z/i7PM/4uzzP+Ls8z/ + i7PM/4uzzP+Ls8z/i7PM/4uzzP+Ls8z/i7PM/4uzzP+Ls8z/i7PM/4uzzP+Ls8z/ibHK/3yjwLd/n78I + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0iDq8b3jbXO/421zv+Ntc7/k6Wt/6ZsPP+nZjH/ + p2Ux/6ZlMf+lZTD/pGQw/6NkMP+iZTP/lJub/421zv+Ntc7/jbXO/421zv+Ntc7/jbXO/421zv+Ntc7/ + jbXO/421zv+Ntc7/jbXO/421zv+Ntc7/jbXO/421zv+Ntc7/jbXO/421zv+Ntc7/jbXO/421zv+Ntc7/ + irLM/3ykwbd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0iErMf3j7fQ/4+30P+Pt9D/ + laav/6htPf+pZzL/qGYx/6dmMf+mZTH/pWUw/6VkMP+jZjT/lZyc/4+30P+Pt9D/j7fQ/5C40P+Vu9L/ + lbvS/5W70v+Vu9L/kLjQ/4+30P+Pt9D/j7fQ/4+30P+Pt9D/j7fQ/4+30P+Pt9D/j7fQ/4+30P+Pt9D/ + j7fQ/4+30P+Pt9D/jLTO/3ykwbd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0iErMj3 + kLjR/5C40f+QuNH/lqiw/6ltPf+raDL/qmcy/6lnMv+oZjH/p2Yx/6ZlMf+lZzT/l52e/5C40f+QuNH/ + kLjR/5zA1v+40uH/udLi/7nS4v+40uH/nMDW/5C40f+QuNH/kLjR/5C40f+QuNH/kLjR/5C40f+QuNH/ + kLjR/5C40f+QuNH/kLjR/5C40f+QuNH/jbXP/3ykwbd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAHifu0iFrcn3krrT/5K60/+SutP/mKmy/6tuPv+saTP/q2gy/6poMv+pZzL/qGcy/6hmMf+maDX/ + mJ+f/5K60/+SutP/krrT/5zA1/+00OH/tdHh/7XR4f+00OH/nMDX/5K60/+SutP/krrT/5K60/+SutP/ + krrT/5K60/+SutP/krrT/5K60/+SutP/krrT/5K60/+SutP/j7fQ/32kwbd/n78IAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHifu0iGrsr3lLzV/5S81f+UvNX/mquz/61wP/+uajP/rWkz/6xoM/+raDL/ + qmcy/6lnMv+oaDX/mqCg/5S81f+UvNX/lLzV/5vB2P+tzN//rszf/67M3/+tzN//m8HY/5S81f+UvNX/ + lLzV/5S81f+UvNX/lLzV/5S81f+UvNX/lLzV/5S81f+UvNX/lLzV/5S81f+UvNX/kbnS/32lwbd/n78I + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHifu0iDq8f3jbXP/421z/+Ntc//laav/65wP/+vajT/ + rmoz/65pM/+taTP/rGgz/6toMv+paTb/lpyd/421z/+Ntc//jbXP/5O50v+hw9j/osPY/6LD2P+hw9j/ + k7nS/421z/+Ntc//jbXP/421z/+Ntc//jbXP/421z/+Ntc//jbXP/421z/+Ntc//jbXP/421z/+Ntc// + irLN/3ykwbd/n78IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHufv0B9o8HyfqTC/36kwv9+pML/ + iZik/69wPv+xazT/sGs0/69qNP+uajP/rWkz/6xpM/+qajb/jZGU/36kwv9+pML/fqTC/4SoxP+Sssv/ + lLTN/5OzzP+Rssv/hKjE/36kwv9+pML/fqTC/36kwv9+pML/fqTC/36kwv9+pML/fqTC/36kwv9+pML/ + fqTC/36kwv9+pML/fqTC/3yjwbKRttoHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH+qyRiEqMXM + hajG/4Woxv+FqMb/j5yo/7FxP/+zbDX/smw1/7FrNP+wazT/r2o0/65qM/+sazf/kZSY/4Woxv+FqMb/ + hajG/4mryP+Vs83/l7bQ/5W0zv+Us83/iavI/4Woxv+FqMb/hajG/4Woxv+FqMb/hajG/4Woxv+FqMb/ + hajG/4Woxv+FqMb/hajG/4Woxv+FqMb/hKfF/IOnw3T///8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAH9//wKHqsiCh6vI/YeryP+Hq8j/kZ6q/7NyQP+1bTb/tG01/7NsNf+ybDX/sWs0/7BqNP+tbDj/ + kpmd/4eryP+Hq8j/h6vI/4uuyv+Vtc7/l7fQ/5W1z/+Vtc7/i67K/4eryP+Hq8j/h6vI/4eryP+Hq8j/ + h6vI/4eryP+Hq8j/h6vI/4eryP+Hq8j/h6vI/4eryP+Hq8j/hqrH4oirySsAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACIrss2ia7K6Ymuyv+Jrsr/k6Gs/7RzQf+3bjb/tm42/7VtNv+0bTX/ + s2w1/7JrNf+wbTj/lpmb/4muyv+Jrsr/ia7K/42xzP+Wt9D/l7jR/5a30P+Wt9D/jbHM/4muyv+Jrsr/ + ia7K/4muyv+Jrsr/ia7K/4muyv+Jrsr/ia7K/4muyv+Jrsr/ia7K/4muyv+Jrsr/iK7LopG22gcAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACLudALi7HMsYyxzf+Msc3/lKaz/7V2Rf+5bzf/ + t282/7ZuNv+1bjb/tG01/7NsNf+ybDb/nJOK/4yxzP+Msc3/jLHN/4+zzv+YudL/mbrT/5i50v+YudL/ + j7PO/4yxzf+Msc3/jLHN/4yxzf+Msc3/jLHN/4yxzf+Msc3/jLHN/4yxzf+Msc3/jLHN/4yxzf+LsMv1 + jLLMUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj7HPYI2zzvmOtM// + k62//7R7T/+6cDf/uXA3/7hvN/+3bzb/tm42/7VtNv+0bTX/qIJk/5CxyP+OtM//jrTP/5G20P+avNT/ + mbvT/5q81P+avNT/kbbQ/460z/+OtM//jrTP/460z/+OtM//jrTP/460z/+OtM//jrTP/460z/+OtM// + jrTP/460z/+OtM/KkLHHFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + j7fPIJC20NeQt9H/krTL/7GFY/+8cjj/u3E4/7pwN/+5cDf/uG83/7dvNv+2bjb/s3I//5yfn/+QttD/ + kLfR/5O50v+bvtb/mr3V/5u+1v+bvtb/k7nS/5C30f+Qt9H/kLfR/5C30f+Qt9H/kLfR/5C30f+Qt9H/ + kLfR/5C30f+Qt9H/kLfR/5C20P2PttB+f39/AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAf7+/BJK505KSudP+k7nT/6mWhf++czr/vXI4/7xxOP+7cTj/unA3/7lwN/+4bzf/ + t242/7B6UP+bp63/k7nS/5W81P+dwdf/m7/W/53B1/+dwdf/lbzU/5K60/+SutP/krrT/5K60/+SutP/ + krrT/5K60/+SutP/krrT/5K60/+SutP/krrT/5G50ueTvNYyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJK91EKUu9XvlLzV/5+rsf+9eUX/v3M5/75yOf+9cjj/ + vHE4/7txOP+6cDf/uG83/7dvN/+yeUz/opuS/5u0w/+gv9P/nb/U/5/B1v+gwdb/mLzT/5W60/+VutP/ + lbrS/5W60v+VutL/lbrS/5W60v+VutL/lbrS/5W60v+VutL/lbrS/5S60a6ZsswKAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJzE1w2WvNZrlb3VgJq1x4G8fk3G + wXQ6/8B0Of+/czn/vnI5/71yOP+8cTj/unA3/7lwN/+4bzf/tnA6/7J6Tv+whmT/rYlr/62JbP+siWz/ + qYdq/6eGav+nhmr/poVp/6WFaf+lhWn/pIRo/6SEaP+jhGj/ooNo/6KDaP+hg2j/oIJn/6B5WLCiXC4L + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAADDdDxEw3U66sJ1Ov/BdDr/wHM5/79zOf+9cjn/vHE4/7txOP+6cDf/uXA3/7hvN/+3bzb/ + tm42/7VtNv+0bTX/s2w1/7JsNf+xazT/sGo0/69qNP+uaTP/rWkz/6xoM/+raDL/qmcy/6lnMv+oZjH/ + p2Yx/6ZlMMevXy8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAC2bUgHxHU6hsN1OvrDdTr/wnQ6/8B0Of+/czn/vnI5/71yOP+8cTj/ + u3E4/7pwN/+5bzf/t282/7ZuNv+1bjb/tG01/7NsNf+ybDX/sWs0/7BrNP+vajT/rmoz/61pM/+saTP/ + q2gy/6poMv+qZzL/qWcy/6dmMMevXy8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxXM5FsV2O6zEdTr9xHY7/8N1Ov/BdDr/ + wHQ5/79zOf++czn/vXI4/7xxOP+7cTj/uXA3/7hvN/+3bzf/tm42/7VuNv+0bTX/s2w1/7JsNf+xazT/ + sGs0/69qNP+uajP/rWkz/6xpM/+raDL/qmgy/6lmMcevby8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMN4PCLGdju0 + xXY6/MV2O//Ddjv/wnU6/8F0Ov/AdDn/v3M5/75yOf+9cjj/u3E4/7pwN/+5cDf/uG83/7dvNv+2bjb/ + tW02/7RtNf+zbDX/smw1/7FrNP+wazT/r2o0/65pM/+taTP/rGgz/6tnMcevby8QAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAADFczkfx3c6oMV3O/bFdzv/xHY7/8N1Ov/CdTr/wXQ6/8BzOf++czn/vXI4/7xxOP+7cTj/ + unA3/7lwN/+4bzf/t242/7ZuNv+1bTb/s201/7JsNf+xbDX/sGs0/69qNP+uajT/rWkz/6xpM8evby8Q + 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 + AAAAAHObuYBslK3/apKr/2qSq/9qkqv/apKr/2qSq/9qkqv/apKr/2qSq/9qkqv/apKr/2qSq/9qkqv/ + apKr/2qSq/9qkqv/apKr/2qSq/9qkqv/apKr/2qSq/9qkqv/apKr/2qSq/9slK3/c5u5gAAAAAAAAAAA + AAAAAAAAAAAAAAAAdZ25gG6WsP9tla7/bZWu/22Vrv9tla7/bZWu/22Vrv9tla7/bZWu/22Vrv9tla7/ + bZWu/22Vrv9tla7/bZWu/22Vrv9tla7/bZWu/22Vrv9tla7/bZWu/22Vrv9tla7/bZWu/26WsP91nbmA + AAAAAAAAAAAAAAAAAAAAAAAAAAB1nbmAcZmz/3CYsf9wmLH/cJix/3CYsf9wmLH/cJix/3CYsf9wmLH/ + cJix/3CYsf9wmLH/cJix/3CYsf9wmLH/cJix/3CYsf9wmLH/cJix/3CYsf9wmLH/cJix/3CYsf9wmLH/ + cZmz/3WduYAAAAAAAAAAAAAAAAAAAAAAAAAAAHefu4B0nLX/c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/ + c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/c5u0/3ObtP9zm7T/ + c5u0/3ObtP90nLX/d5+7gAAAAAAAAAAAAAAAAAAAAAAAAAAAd5+7gHefuf93n7j/d5+4/3efuP93n7j/ + d5+4/3efuP93n7j/d5+4/3efuP93n7j/d5+4/3efuP93n7j/d5+4/3efuP93n7j/d5+4/3efuP93n7j/ + d5+4/3efuP93n7j/d5+4/3efuf93n7uAAAAAAAAAAAAAAAAAAAAAAAAAAAB3n72AeqK7/3qiu/96orv/ + eqK7/3qhuf9/l6P/e5+1/3qiu/96orv/eqK7/3qiu/96orv/eqK7/3qiu/96orv/eqK7/3qiu/96orv/ + eqK7/3qiu/96orv/eqK7/3qiu/96orv/eqK7/3efvYAAAAAAAAAAAAAAAAAAAAAAAAAAAHmhvYB8pL7/ + faW+/32lvv99pLz/h46O/5dqQ/+Lgnb/fqK4/32lvv99pb7/faW+/32lvv99pb7/faW+/32lvv99pb7/ + faW+/32lvv99pb7/faW+/32lvv99pb7/faW+/32lvv98pL7/eaG9gAAAAAAAAAAAAAAAAAAAAAAAAAAA + eaG9gH+nwf+AqMH/gKe//4qQkP+baD7/nWAu/5tjNP+NhHj/gaW7/4Cowf+AqMH/gKjB/4Cowf+AqMH/ + gKjB/4Cowf+AqMH/gKjB/4Cowf+AqMH/gKjB/4Cowf+AqMH/gKjB/3+nwf95ob2AAAAAAAAAAAAAAAAA + AAAAAAAAAAB5ob+AgqrD/4Oqwv+Nk5L/nWo//6BiL/+fYS7/nmEu/5xjNf+Phnr/hKi+/4OrxP+Dq8T/ + g6vE/4OrxP+Dq8T/g6vE/4OrxP+Dq8T/g6vE/4OrxP+Dq8T/g6vE/4OrxP+Dq8T/gqrD/3mhv4AAAAAA + AAAAAAAAAAAAAAAAAAAAAHujv4CEq8T/kJWV/6BsQP+jYzD/omMv/6FiL/+fYi//n2Eu/51kNf+Rh3z/ + h6vB/4aux/+Grsf/hq7H/4aux/+Grsf/hq7H/4aux/+Grsf/hq7H/4aux/+Grsf/hq7H/4aux/+ErMb/ + e6O/gAAAAAAAAAAAAAAAAAAAAAAAAAAAe6O/gI+bof+hdE7/pGo7/6VlMf+kZDD/o2Mw/6FjL/+gYi// + nmU1/5trQv+RkIr/ia/H/4mxyv+Jscr/ibHK/4mxyv+Jscr/ibHK/4mxyv+Jscr/ibHK/4mxyv+Jscr/ + ibHK/4evyP97o8GAAAAAAAAAAAAAAAAAAAAAAAAAAAB9o7+Ajam6/5Gmsf+Vmpr/pWs8/6ZlMf+lZDD/ + o2Qw/6JjL/+Zgmz/j6Wx/46otv+Mssr/i7PM/4uzzP+Ls8z/i7PM/4uzzP+Ls8z/i7PM/4uzzP+Ls8z/ + i7PM/4uzzP+Ls8z/ibHL/32lwYAAAAAAAAAAAAAAAAAAAAAAAAAAAH2lwYCLs83/jrbP/5Oos/+nbj// + qGYx/6dlMf+lZTH/pGQw/5mKe/+Ots//jrbP/5G40f+VutL/lbrS/5G40f+Ots//jrbP/462z/+Ots// + jrbP/462z/+Ots//jrbP/462z/+Ls83/faXBgAAAAAAAAAAAAAAAAAAAAAAAAAAAfaXDgI620P+RudL/ + lqu2/6lvQP+qaDL/qWcy/6hmMf+mZTH/nI18/5G50v+RudL/pMXa/7bR4f+20eH/pMXa/5G50v+RudL/ + kbnS/5G50v+RudL/kbnS/5G50v+RudL/kbnS/4620P99pcOAAAAAAAAAAAAAAAAAAAAAAAAAAAB/p8OA + kLjR/5O71P+Yrbj/rHFB/61pM/+raDL/qmcy/6lnMv+ejn7/k7vU/5O71P+ixdr/sM3g/7DN4P+ixdr/ + k7vU/5O71P+Tu9T/k7vU/5O71P+Tu9T/k7vU/5O71P+Tu9T/kLjR/3+nw4AAAAAAAAAAAAAAAAAAAAAA + AAAAAHyiwH+Grcn/iK/L/4+jsP+tcUH/r2o0/65pM/+saTP/q2gy/5qJev+Ir8v/iK/L/5O30P+evtT/ + nb7U/5O30P+Ir8v/iK/L/4ivy/+Ir8v/iK/L/4ivy/+Ir8v/iK/L/4ivy/+Grcn/faPBgAAAAAAAAAAA + AAAAAAAAAAAAAAAAgqXCWIKmxPiDp8T/jJ2r/69xQf+ybDX/sGs0/69qNP+taTP/mYZ4/4OnxP+Dp8T/ + jK3J/5W1zv+VtM3/jK3J/4OnxP+Dp8T/g6fE/4OnxP+Dp8T/g6fE/4OnxP+Dp8T/g6fE/4OmxPmCpcNe + AAAAAAAAAAAAAAAAAAAAAAAAAACDp8Edh6zI1Iisyf+Qoa//snNC/7VtNv+zbDX/sms1/7BrNP+ci33/ + iKzJ/4isyf+Pscz/lrfQ/5W2z/+Pscz/iKzJ/4isyf+IrMn/iKzJ/4isyf+IrMn/iKzJ/4isyf+IrMn/ + h6vH2IenxyAAAAAAAAAAAAAAAAAAAAAAAAAAAKqqqgOKsMuMi7DL/pKmtf+0dkb/t282/7ZuNv+0bTX/ + s2w1/6KIc/+LsMv/i7DM/5G1z/+YudL/l7nR/5G1z/+LsMz/i7DM/4uwzP+LsMz/i7DM/4uwzP+LsMz/ + i7DM/4uwzP6Kr8uRf7+/BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI6z0T2Os87uk67B/7R8UP+6cDf/ + uW83/7dvNv+1bjb/rXpT/5Ktv/+PtdD/lbnT/5q81P+avNX/lbnT/4+10P+PtdD/j7XQ/4+10P+PtdD/ + j7XQ/4+10P+PtdD/jrTQ74+zz0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkbbaDpC40buTt87/ + sIlq/71yOP+7cTj/unA3/7hvN/+2cDn/pY98/5S0yv+YvdX/nL/W/53A1/+YvdX/krnT/5K50/+SudP/ + krnT/5K50/+SudP/krnT/5K50/+RuNK9iLvMDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8B + lbzVY5S81d2nnZLkv3Q6/L5zOf+9cjj/u3E4/7lwN/+2cTz/q4hr/6Ompf+jsLf/o7K5/5+vuP+arLb/ + mqy2/5mstv+ZrLb/mau2/5irtf+Yq7X/l6q0/piosHz/AP8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACZsswKlL3VH6uWgjHBdTrIwXQ6/8BzOf++cjn/vHI4/7pxOP+5cDf/tnE7/7RzQf+zc0H/ + sXJA/69xQP+ucD//rHA//6tvPv+qbj7/qG0+/6dtPf+mbDz/pWg3i/8AAAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAcR1Ok7EdTrqw3U6/8F0Ov+/czn/vXI5/7xxOP+6cDf/ + uG83/7duNv+1bjb/tG01/7JsNf+xazT/r2o0/65pM/+saTP/q2gy/6lnMv+nZTGP/wAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzGYzBcV3O2vFdjvtxHY7/8J1Ov/AdDr/ + v3M5/71yOP+7cTj/unA3/7hvN/+2bjb/tW02/7NsNf+ybDX/sGs0/69qNP+taTP/rGgz/6lnMY//AAAB + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtm1IB8Z3O17GdzvZ + xXY7/cN1O//CdTr/wHQ5/75zOf+8cjj/u3E4/7lwN/+4bzf/tm42/7RtNf+zbDX/sWs0/7BrNP+uajP/ + rGkzj/8AAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + /39/AsVzOSzGdzuNxnc718R2O/XCdDr9wXQ6/r9zOf+9cjn/vHE4/7pxOP+5cDf/t282/7ZuNv+0bTX/ + smw1/7FrNP+uaTOP/wAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAL9/PwTMdzsexng8SMV1OWrCdTl3wXQ5eL5yN3u+cjh/u3E3gLlvN4C3bzWA + t201gLVtNYC0bDZ/sms1e7JqNUP/AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////8AAAAfAAAAH + wAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAH + wAAAB8AAAAfAAAAHwAAAB+AAAA/gAAAP4AAAD/AAAA/8AAAP/gAAD/8AAA//gAAP/+AAD/////8oAAAA + EAAAACAAAAABACAAAAAAAEAEAAAAAAAAAAAAAAAAAAAAAAAAf3//AnObuTNxmLRIcZi0SHGYtEhxmLRI + cZi0SHGYtEhxmLRIcZi0SHGYtEhxmLRIcZi0SHKbtUVymb8UAAAAAH+fvwhul7KxapKr92qSq/dqkqv3 + apKr92qSq/dqkqv3apKr92qSq/dqkqv3apKr92qSq/drlK3vcJi2RgAAAAB/n78Icpq1t2+XsP9vl7D/ + b5ew/2+XsP9vl7D/b5ew/2+XsP9vl7D/b5ew/2+XsP9vl7D/b5ew93SbuEgAAAAAf5+/CHaeubd1nbb/ + dZ22/3Wdtv91nbb/dZ22/3Wdtv91nbb/dZ22/3Wdtv91nbb/dZ22/3Wctvd0n7hIAAAAAH+fvwh6o723 + e6O8/4CZqP+Gioj/fKC2/3ujvP97o7z/e6O8/3ujvP97o7z/e6O8/3ujvP96o7v3eJ+7SAAAAAB/n78I + fqfBt4afrf+XdFb/nGQ1/46EeP+Cprz/ganC/4Gpwv+BqcL/ganC/4Gpwv+BqcL/gKjC93uiv0gAAAAA + f5+/CIehs7eaf2f/o2Uy/6FiL/+dZzn/kI+K/4euxv+Hr8j/h6/I/4evyP+Hr8j/h6/I/4atx/d/psJI + AAAAAH+fvwiIq8C3lKCk/6VtP/+lZTD/nnZU/5Cptv+Rt87/kbjQ/421zv+Ntc7/jbXO/421zv+Lssz3 + f6nCSAAAAAB/n78IibLMt5Wtuv+pcUP/qWcy/6F8Xf+Tt83/p8fb/6fH2/+SutP/kbnS/5G50v+RudL/ + jrbQ94OpxkgAAAAAf6qqBoSrx6qNorL/rXJD/65qM/+ie1v/iKrD/5W2z/+Vts//h6zI/4asyP+GrMj/ + hqzI/4Wrx/OBqcY/AAAAAAAAAACJrclkj6W0+rF1Rv+0bTX/p3xb/4yrxP+Ttc//k7XP/4muyv+Jrsr/ + ia7K/4muyv+JrcrMhabHFwAAAAAAAAAAjrTSIpOuwdu0flT/uXA3/7J1Rf+ZpKr/mLvS/5i81P+Qt9H/ + kLfR/5C30f+QttD9jrTQf39/fwIAAAAAAAAAAH+/vwSWuM5atoRcs75yOP27cTj/tHpN/6yOdf+pkn3/ + pI57/6KNev+hjXr/n4t4+J2JdUwAAAAAAAAAAAAAAAAAAAAAAAAAAMN4PCLDdTrBwHQ5/r5yOf+7cTj/ + t282/7RtNf+xazT/rmoz/6toMvmpaDFOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyXg8JsV3OpzDdDrj + wHQ59LxyN/a5bzb3tm4197NsNPevajPxrWkySwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADakUgH + xXI5KMR1OkHAcjtFu3E4SLhtNUi0bTVIsWszRbZtMBUAAAAAAAAAAAABJgAAASYAAAEmAAABJgAAASYA + AAEmAAABJgAAASYAAAEmAAABJgCAASYAgAEmAIADJgDgAyYA8AMmAPgDJgA= + + + \ No newline at end of file diff --git a/Pilz.Updating.Updater/UpdateInstaller.vb b/Pilz.Updating.Updater/UpdateInstaller.vb new file mode 100644 index 0000000..6daede9 --- /dev/null +++ b/Pilz.Updating.Updater/UpdateInstaller.vb @@ -0,0 +1,115 @@ +Imports System.IO +Imports Newtonsoft.Json.Linq +Imports Pilz.Updating.Model +Imports Pilz.Updating.Scripts + +Public Class UpdateInstaller + + Private restartHostApplication As Boolean + Private autoCloseHostApplication As Boolean + Private packageDir As String + Private appExePath As String + + Private Sub UpdateInstaller_Shown(sender As Object, e As EventArgs) Handles Me.Shown + CheckCommandLines() + + If autoCloseHostApplication Then + CloseHostApplication() + End If + + InstallUpdates() + + If restartHostApplication Then + StartHostApplication() + End If + End Sub + + Private Sub CloseHostApplication() + Dim myProcesses As New List(Of Process) + + For Each p As Process In Process.GetProcesses + If p.MainModule.FileName = appExePath Then + myProcesses.Add(p) + End If + Next + + For Each p As Process In myProcesses + p.Close() + Next + + Dim waited As Byte = 5 + Do While myProcesses.Where(Function(n) Not n.HasExited).Any AndAlso waited > 0 + Sleep(1000) + waited -= 1 + Loop + + For Each p As Process In myProcesses + If Not p.HasExited Then + p.Kill() + End If + Next + End Sub + + Private Sub StartHostApplication() + Process.Start(appExePath) + End Sub + + Private Sub CheckCommandLines() + For Each cmd As String In My.Application.CommandLineArgs + Dim splitted As String() = cmd.Split("#") + + If splitted.Length = 2 Then + Select Case splitted(0).ToLower + Case "restartHostApp".ToLower + restartHostApplication = splitted(1) + Case "autoCloseHostApp".ToLower + autoCloseHostApplication = splitted(1) + Case "updatePackage".ToLower + packageDir = splitted(1) + Case "applicationPath" + appExePath = splitted(1) + End Select + End If + Next + End Sub + + Private Sub InstallUpdates() + Dim packagePath As String = Path.Combine(packageDir, "package.json") + Dim packageFilesDir As String = Path.Combine(packageDir, "files") + Dim systemFilesDir As String = Path.GetDirectoryName(appExePath) + + 'Load update package + Dim package As UpdatePackage = JObject.Parse(File.ReadAllText(packagePath)).ToObject(Of UpdatePackage) + + 'Execute ScriptBefore + ExecuteScriptsWithPriority(ScriptPriority.Before, package.Scripts, systemFilesDir, packageFilesDir) + + 'Update Files + For Each rFile As String In package.Fileupdates + Dim packageFile As String = Path.Combine(packageFilesDir, rFile) + Dim systemFile As String = Path.Combine(systemFilesDir, rFile) + Dim systemFileDir As String = Path.GetDirectoryName(systemFile) + + 'Create destination directory if not exists + If Not Directory.Exists(systemFileDir) Then + Directory.CreateDirectory(systemFileDir) + End If + + 'Copy package file to system file + File.Copy(packageFile, systemFile, True) + Next + + 'ExecuteScriptAfter + ExecuteScriptsWithPriority(ScriptPriority.After, package.Scripts, systemFilesDir, packageFilesDir) + End Sub + + Private Sub ExecuteScriptsWithPriority(priority As ScriptPriority, scripts As IEnumerable(Of Script), applicationPath As String, updatePackagePath As String) + For Each script As Script In scripts + If script.Priority = priority Then + Dim mgr As New ScriptManager(applicationPath, updatePackagePath) + mgr.ExecuteScript(script) + End If + Next + End Sub + +End Class diff --git a/Pilz.Updating.Updater/packages.config b/Pilz.Updating.Updater/packages.config new file mode 100644 index 0000000..93b0be8 --- /dev/null +++ b/Pilz.Updating.Updater/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Pilz.Updating/General.vb b/Pilz.Updating/General.vb new file mode 100644 index 0000000..822d1ef --- /dev/null +++ b/Pilz.Updating/General.vb @@ -0,0 +1,21 @@ +Imports System.IO + +Public Module General + + Public ReadOnly Property MyTempPath As String + Get + Static p As String = String.Empty + + If String.IsNullOrEmpty(p) Then + p = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Pilz.Updating") + + If Not Directory.Exists(p) Then + Directory.CreateDirectory(p) + End If + End If + + Return p + End Get + End Property + +End Module diff --git a/Pilz.Updating/Model/BuildState.vb b/Pilz.Updating/Model/BuildState.vb new file mode 100644 index 0000000..60a6871 --- /dev/null +++ b/Pilz.Updating/Model/BuildState.vb @@ -0,0 +1,10 @@ +Namespace Model + + Public Enum BuildState + Release + ReleaseCandidate + Beta + Alpha + End Enum + +End Namespace diff --git a/Pilz.Updating/Model/CodeLanguage.vb b/Pilz.Updating/Model/CodeLanguage.vb new file mode 100644 index 0000000..66a1911 --- /dev/null +++ b/Pilz.Updating/Model/CodeLanguage.vb @@ -0,0 +1,8 @@ +Namespace Model + + Public Enum CodeLanguage + VB + CSharp + End Enum + +End Namespace diff --git a/Pilz.Updating/Model/UpdateInfo.vb b/Pilz.Updating/Model/UpdateInfo.vb new file mode 100644 index 0000000..ffbcc9f --- /dev/null +++ b/Pilz.Updating/Model/UpdateInfo.vb @@ -0,0 +1,13 @@ +Namespace Model + + Public Class UpdateInfo + + Public Property Name As String + Public Property Version As Version + Public Property State As BuildState + Public Property Build As UInteger + Public Property Changelog As String + + End Class + +End Namespace diff --git a/Pilz.Updating/Model/UpdatePackage.vb b/Pilz.Updating/Model/UpdatePackage.vb new file mode 100644 index 0000000..5978157 --- /dev/null +++ b/Pilz.Updating/Model/UpdatePackage.vb @@ -0,0 +1,12 @@ +Imports Pilz.Updating.Scripts + +Namespace Model + + Public Class UpdatePackage + + Public ReadOnly Property Fileupdates As New List(Of String) + Public ReadOnly Property Scripts As New List(Of Script) + + End Class + +End Namespace diff --git a/Pilz.Updating/My Project/Application.Designer.vb b/Pilz.Updating/My Project/Application.Designer.vb new file mode 100644 index 0000000..88dd01c --- /dev/null +++ b/Pilz.Updating/My Project/Application.Designer.vb @@ -0,0 +1,13 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + diff --git a/Pilz.Updating/My Project/Application.myapp b/Pilz.Updating/My Project/Application.myapp new file mode 100644 index 0000000..758895d --- /dev/null +++ b/Pilz.Updating/My Project/Application.myapp @@ -0,0 +1,10 @@ + + + false + false + 0 + true + 0 + 1 + true + diff --git a/Pilz.Updating/My Project/AssemblyInfo.vb b/Pilz.Updating/My Project/AssemblyInfo.vb new file mode 100644 index 0000000..8941d19 --- /dev/null +++ b/Pilz.Updating/My Project/AssemblyInfo.vb @@ -0,0 +1,35 @@ +Imports System +Imports System.Reflection +Imports System.Runtime.InteropServices + +' Allgemeine Informationen über eine Assembly werden über die folgenden +' Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +' die einer Assembly zugeordnet sind. + +' Werte der Assemblyattribute überprüfen + + + + + + + + + + +'Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird. + + +' Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +' +' Hauptversion +' Nebenversion +' Buildnummer +' Revision +' +' Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +' übernehmen, indem Sie "*" eingeben: +' + + + diff --git a/Pilz.Updating/My Project/Resources.Designer.vb b/Pilz.Updating/My Project/Resources.Designer.vb new file mode 100644 index 0000000..af39fa0 --- /dev/null +++ b/Pilz.Updating/My Project/Resources.Designer.vb @@ -0,0 +1,62 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My.Resources + + 'This class was auto-generated by the StronglyTypedResourceBuilder + 'class via a tool like ResGen or Visual Studio. + 'To add or remove a member, edit your .ResX file then rerun ResGen + 'with the /str option, or rebuild your VS project. + ''' + ''' A strongly-typed resource class, for looking up localized strings, etc. + ''' + _ + Friend Module Resources + + Private resourceMan As Global.System.Resources.ResourceManager + + Private resourceCulture As Global.System.Globalization.CultureInfo + + ''' + ''' Returns the cached ResourceManager instance used by this class. + ''' + _ + Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager + Get + If Object.ReferenceEquals(resourceMan, Nothing) Then + Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Pilz.Updating.Resources", GetType(Resources).Assembly) + resourceMan = temp + End If + Return resourceMan + End Get + End Property + + ''' + ''' Overrides the current thread's CurrentUICulture property for all + ''' resource lookups using this strongly typed resource class. + ''' + _ + Friend Property Culture() As Global.System.Globalization.CultureInfo + Get + Return resourceCulture + End Get + Set(ByVal value As Global.System.Globalization.CultureInfo) + resourceCulture = value + End Set + End Property + End Module +End Namespace diff --git a/Pilz.Updating/My Project/Resources.resx b/Pilz.Updating/My Project/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Pilz.Updating/My Project/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Pilz.Updating/My Project/Settings.Designer.vb b/Pilz.Updating/My Project/Settings.Designer.vb new file mode 100644 index 0000000..b7968de --- /dev/null +++ b/Pilz.Updating/My Project/Settings.Designer.vb @@ -0,0 +1,73 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + _ + Partial Friend NotInheritable Class MySettings + Inherits Global.System.Configuration.ApplicationSettingsBase + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings) + +#Region "My.Settings Auto-Save Functionality" +#If _MyType = "WindowsForms" Then + Private Shared addedHandler As Boolean + + Private Shared addedHandlerLockObject As New Object + + _ + Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) + If My.Application.SaveMySettingsOnExit Then + My.Settings.Save() + End If + End Sub +#End If +#End Region + + Public Shared ReadOnly Property [Default]() As MySettings + Get + +#If _MyType = "WindowsForms" Then + If Not addedHandler Then + SyncLock addedHandlerLockObject + If Not addedHandler Then + AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings + addedHandler = True + End If + End SyncLock + End If +#End If + Return defaultInstance + End Get + End Property + End Class +End Namespace + +Namespace My + + _ + Friend Module MySettingsProperty + + _ + Friend ReadOnly Property Settings() As Global.Pilz.Updating.My.MySettings + Get + Return Global.Pilz.Updating.My.MySettings.Default + End Get + End Property + End Module +End Namespace diff --git a/Pilz.Updating/My Project/Settings.settings b/Pilz.Updating/My Project/Settings.settings new file mode 100644 index 0000000..85b890b --- /dev/null +++ b/Pilz.Updating/My Project/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Pilz.Updating/MyEventArgs/UpdatesFoundEventArgs.vb b/Pilz.Updating/MyEventArgs/UpdatesFoundEventArgs.vb new file mode 100644 index 0000000..e3e33c0 --- /dev/null +++ b/Pilz.Updating/MyEventArgs/UpdatesFoundEventArgs.vb @@ -0,0 +1,17 @@ +Imports Pilz.Updating.Model + +Namespace MyEventArgs + + Public Class UpdatesFoundEventArgs + Inherits EventArgs + + Public Property Cancel As Boolean = False + Public Property Updates As UpdateInfo() + + Public Sub New(updates As UpdateInfo()) + Me.Updates = updates + End Sub + + End Class + +End Namespace diff --git a/Pilz.Updating/Pilz.Updating.vbproj b/Pilz.Updating/Pilz.Updating.vbproj new file mode 100644 index 0000000..d024abb --- /dev/null +++ b/Pilz.Updating/Pilz.Updating.vbproj @@ -0,0 +1,119 @@ + + + + + Debug + AnyCPU + {354255D9-9536-4400-B915-FFC49C2CE93F} + Library + Pilz.Updating + Pilz.Updating + 512 + Windows + v4.5 + true + + + true + full + true + true + bin\Debug\ + Pilz.Updating.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + pdbonly + false + true + true + bin\Release\ + Pilz.Updating.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + On + + + Binary + + + Off + + + On + + + + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + Application.myapp + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + VbMyResourcesResXFileCodeGenerator + Resources.Designer.vb + My.Resources + Designer + + + + + MyApplicationCodeGenerator + Application.Designer.vb + + + SettingsSingleFileGenerator + My + Settings.Designer.vb + + + + \ No newline at end of file diff --git a/Pilz.Updating/Scripts/Script.vb b/Pilz.Updating/Scripts/Script.vb new file mode 100644 index 0000000..a7f7ae9 --- /dev/null +++ b/Pilz.Updating/Scripts/Script.vb @@ -0,0 +1,13 @@ +Imports Pilz.Updating.Model + +Namespace Scripts + + Public Class Script + + Public Property Priority As ScriptPriority = ScriptPriority.Before + Public Property Language As CodeLanguage = CodeLanguage.CSharp + Public Property Code As String + + End Class + +End Namespace diff --git a/Pilz.Updating/Scripts/ScriptManager.vb b/Pilz.Updating/Scripts/ScriptManager.vb new file mode 100644 index 0000000..325e310 --- /dev/null +++ b/Pilz.Updating/Scripts/ScriptManager.vb @@ -0,0 +1,71 @@ +Imports System.CodeDom.Compiler +Imports System.Reflection +Imports Microsoft.CSharp +Imports Pilz.Updating.Model +Imports Pilz.Updating.Scripts + +Namespace Scripts + + Public Class ScriptManager + + Public Property ApplicationPath As String + Public Property UpdatePackagePath As String + + Public Sub New(applicationPath As String, updatePackagePath As String) + Me.ApplicationPath = applicationPath + Me.UpdatePackagePath = updatePackagePath + End Sub + + Private Function CompileScript(script As Script) As CompilerResults + Dim provider As CodeDomProvider = Nothing + Dim params As New CompilerParameters + + 'Create code provider + Select Case script.Language + Case CodeLanguage.CSharp + provider = New CSharpCodeProvider + Case CodeLanguage.VB + provider = New VBCodeProvider + End Select + + 'Set general options + params.GenerateExecutable = False + params.GenerateInMemory = True + + 'Set references + params.ReferencedAssemblies.Add() + + 'Compile + Dim res As CompilerResults = provider.CompileAssemblyFromSource(params, script.Code) + + Return res + End Function + + Public Function CheckScriptForErrors(script As Script) As CompilerErrorCollection + Return CompileScript(script).Errors + End Function + + Public Sub ExecuteScript(script As Script) + 'Compile script + Dim res As CompilerResults = CompileScript(script) + + If Not res.Errors.HasErrors Then + 'Get Method + Dim mi As MethodInfo = res.CompiledAssembly.GetType("Program")?.GetMethod("Main") + + If mi IsNot Nothing Then + 'Create params + Dim params As New Dictionary(Of String, String) From { + {"ApplicationPath", ApplicationPath}, + {"UpdatePackagePath", UpdatePackagePath} + } + + 'Execute method + mi.Invoke(Nothing, {params}) + End If + End If + End Sub + + End Class + +End Namespace diff --git a/Pilz.Updating/Scripts/ScriptPriority.vb b/Pilz.Updating/Scripts/ScriptPriority.vb new file mode 100644 index 0000000..f2835a5 --- /dev/null +++ b/Pilz.Updating/Scripts/ScriptPriority.vb @@ -0,0 +1,8 @@ +Namespace Scripts + + Public Enum ScriptPriority + Before + After + End Enum + +End Namespace diff --git a/Pilz.Updating/UpdateManager b/Pilz.Updating/UpdateManager new file mode 100644 index 0000000..875798b --- /dev/null +++ b/Pilz.Updating/UpdateManager @@ -0,0 +1,3 @@ +Public Class Class1 + +End Class diff --git a/Pilz.Updating/Updater.vb b/Pilz.Updating/Updater.vb new file mode 100644 index 0000000..fbd27df --- /dev/null +++ b/Pilz.Updating/Updater.vb @@ -0,0 +1,86 @@ +Imports System.IO +Imports System.IO.Compression +Imports System.Net +Imports System.Reflection +Imports Newtonsoft.Json.Linq +Imports Pilz.Updating.Model +Imports Pilz.Updating.MyEventArgs + +Public Class Updater + + Public Event UpdatesFound(sender As Object, e As UpdatesFoundEventArgs) + Public Event NoUpdatesFound(sender As Object, e As EventArgs) + Public Event UpdateInstallerStarted(Sender As Object, e As EventArgs) + + Public Property InstallAsAdmin As Boolean = True + Public Property RestartHostApplication As Boolean = True + Public Property AutomaticlyCloseHostApplication As Boolean = True + Public Property UpdateDirURL As String + Public Property UpdateInfoURL As String + + Public Sub New(updateUrl As String) + UpdateInfoURL = updateUrl + UpdateDirURL = updateUrl.Remove(updateUrl.LastIndexOf("/"c)) + End Sub + + Public Async Function Update() As Task + Dim wc As New WebClient + Dim updateInstallerZipPath As String = Path.Combine(MyTempPath, "Pilz.Updating.UpdateInstaller.zip") + Dim updateInstallerPath As String = updateInstallerZipPath & "_unpacked" + Dim updateInstallerExePath As String = Path.Combine(updateInstallerPath, "Pilz.Updating.UpdateInstaller.exe") + + 'Clean AppData + For Each dir As String In Directory.GetDirectories(MyTempPath, "*", SearchOption.TopDirectoryOnly) + Directory.Delete(dir, True) + Next + + 'Download UpdateInfos + Dim strUpdateInfos As String = Await wc.DownloadStringTaskAsync(UpdateInfoURL) + Dim updateInfos As UpdateInfo() = JArray.Parse(strUpdateInfos).ToObject(Of UpdateInfo()) + + If updateInfos.Any Then + 'Order update infos from newest to oldest + updateInfos = updateInfos.OrderByDescending( + Function(n) + Return n.Version.ToString & + (Byte.MaxValue - n.State).ToString("X2") & + n.Build.ToString("X4") + End Function).ToArray + + 'Interagate with user + Dim e As New UpdatesFoundEventArgs(updateInfos) + RaiseEvent UpdatesFound(Me, e) + + 'Install updates + If Not e.Cancel Then + Dim updateInfo As UpdateInfo = updateInfos(0) + Dim updatePackageZipFilename As String = $"{updateInfo.Version.ToString} {CByte(updateInfo.State)} {updateInfo.Build}.zip" + Dim updatePackageZipPath As String = Path.Combine(MyTempPath, updatePackageZipFilename) + Dim updatePackagePath As String = updatePackageZipPath & "_unpacked" + + 'Download UpdateInstaller + Await wc.DownloadFileTaskAsync(UpdateDirURL & "/Pilz.Updating.UpdateInstaller.zip", updateInstallerZipPath) + ZipFile.ExtractToDirectory(updateInstallerZipPath, updateInstallerPath) + + 'Download Update Package + Await wc.DownloadFileTaskAsync(UpdateDirURL & "/" & updatePackageZipFilename, updatePackageZipPath) + ZipFile.ExtractToDirectory(updatePackageZipFilename, updatePackagePath) + + 'Build process arguments + Dim applicationExePath As String = Assembly.GetExecutingAssembly.Location + Dim procArgs As String = $"restartHostApp#{RestartHostApplication} autoCloseHostApp#{AutomaticlyCloseHostApplication} ""updatePackage#{updatePackagePath}"" ""applicationPath#{applicationExePath}""" + + 'Finally start update installer to install updates + Process.Start(updateInstallerExePath, procArgs) + + 'Interagate with user + RaiseEvent UpdateInstallerStarted(Me, New EventArgs) + End If + Else + RaiseEvent NoUpdatesFound(Me, New EventArgs) + End If + + wc.Dispose() + End Function + +End Class diff --git a/Pilz.Updating/packages.config b/Pilz.Updating/packages.config new file mode 100644 index 0000000..93b0be8 --- /dev/null +++ b/Pilz.Updating/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Pilz.sln b/Pilz.sln index aba4084..c7094ce 100644 --- a/Pilz.sln +++ b/Pilz.sln @@ -29,6 +29,12 @@ Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Pilz.Simple3DFileParser", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pilz.LicenseHelper", "Pilz.LicenseHelper\Pilz.LicenseHelper.csproj", "{67593FF7-C1D1-4529-98C4-61CBD0615F08}" EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Pilz.Updating", "Pilz.Updating\Pilz.Updating.vbproj", "{354255D9-9536-4400-B915-FFC49C2CE93F}" +EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Pilz.Updating.UpdateInstaller", "Pilz.Updating.Updater\Pilz.Updating.UpdateInstaller.vbproj", "{1BA3D8E8-C514-4182-9E6E-9E6BB7AF0403}" +EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Pilz.Networking", "Pilz.Networking\Pilz.Networking.vbproj", "{4584B121-09C6-40AC-849B-7E410125EF66}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -141,6 +147,30 @@ Global {67593FF7-C1D1-4529-98C4-61CBD0615F08}.Release|Any CPU.Build.0 = Release|Any CPU {67593FF7-C1D1-4529-98C4-61CBD0615F08}.Release|x86.ActiveCfg = Release|Any CPU {67593FF7-C1D1-4529-98C4-61CBD0615F08}.Release|x86.Build.0 = Release|Any CPU + {354255D9-9536-4400-B915-FFC49C2CE93F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {354255D9-9536-4400-B915-FFC49C2CE93F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {354255D9-9536-4400-B915-FFC49C2CE93F}.Debug|x86.ActiveCfg = Debug|Any CPU + {354255D9-9536-4400-B915-FFC49C2CE93F}.Debug|x86.Build.0 = Debug|Any CPU + {354255D9-9536-4400-B915-FFC49C2CE93F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {354255D9-9536-4400-B915-FFC49C2CE93F}.Release|Any CPU.Build.0 = Release|Any CPU + {354255D9-9536-4400-B915-FFC49C2CE93F}.Release|x86.ActiveCfg = Release|Any CPU + {354255D9-9536-4400-B915-FFC49C2CE93F}.Release|x86.Build.0 = Release|Any CPU + {1BA3D8E8-C514-4182-9E6E-9E6BB7AF0403}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1BA3D8E8-C514-4182-9E6E-9E6BB7AF0403}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1BA3D8E8-C514-4182-9E6E-9E6BB7AF0403}.Debug|x86.ActiveCfg = Debug|Any CPU + {1BA3D8E8-C514-4182-9E6E-9E6BB7AF0403}.Debug|x86.Build.0 = Debug|Any CPU + {1BA3D8E8-C514-4182-9E6E-9E6BB7AF0403}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1BA3D8E8-C514-4182-9E6E-9E6BB7AF0403}.Release|Any CPU.Build.0 = Release|Any CPU + {1BA3D8E8-C514-4182-9E6E-9E6BB7AF0403}.Release|x86.ActiveCfg = Release|Any CPU + {1BA3D8E8-C514-4182-9E6E-9E6BB7AF0403}.Release|x86.Build.0 = Release|Any CPU + {4584B121-09C6-40AC-849B-7E410125EF66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4584B121-09C6-40AC-849B-7E410125EF66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4584B121-09C6-40AC-849B-7E410125EF66}.Debug|x86.ActiveCfg = Debug|Any CPU + {4584B121-09C6-40AC-849B-7E410125EF66}.Debug|x86.Build.0 = Debug|Any CPU + {4584B121-09C6-40AC-849B-7E410125EF66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4584B121-09C6-40AC-849B-7E410125EF66}.Release|Any CPU.Build.0 = Release|Any CPU + {4584B121-09C6-40AC-849B-7E410125EF66}.Release|x86.ActiveCfg = Release|Any CPU + {4584B121-09C6-40AC-849B-7E410125EF66}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Pilz/HelpfulFunctions.vb b/Pilz/HelpfulFunctions.vb new file mode 100644 index 0000000..1418dd3 --- /dev/null +++ b/Pilz/HelpfulFunctions.vb @@ -0,0 +1,17 @@ +Imports System.Windows.Forms + +Public Module HelpfulFunctions + + Public Sub Sleep(milliseconds As Integer) + Dim stopw As New Stopwatch + + stopw.Start() + + Do While stopw.ElapsedMilliseconds < milliseconds + Application.DoEvents() + Loop + + stopw.Stop() + End Sub + +End Module diff --git a/Pilz/Pilz.vbproj b/Pilz/Pilz.vbproj index d0f8cda..91edc17 100644 --- a/Pilz/Pilz.vbproj +++ b/Pilz/Pilz.vbproj @@ -46,6 +46,7 @@ + @@ -64,6 +65,7 @@ + True diff --git a/Shared Libs/AssimpNet.dll b/Shared Libs/AssimpNet.dll new file mode 100644 index 0000000..e20102a Binary files /dev/null and b/Shared Libs/AssimpNet.dll differ diff --git a/Shared Libs/ColladaSchema.dll b/Shared Libs/ColladaSchema.dll new file mode 100644 index 0000000..f367603 Binary files /dev/null and b/Shared Libs/ColladaSchema.dll differ